Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4 LT |
2 | /* |
3 | * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux | |
4 | * | |
ab0c3443 DT |
5 | * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz> |
6 | * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org> | |
1da177e4 LT |
7 | * |
8 | * Based on the work of: | |
ab0c3443 DT |
9 | * Andree Borrmann John Dahlstrom |
10 | * David Kuder Nathan Hand | |
b157d55e | 11 | * Raphael Assenat |
1da177e4 LT |
12 | */ |
13 | ||
14 | /* | |
1da177e4 LT |
15 | */ |
16 | ||
a1e12747 DT |
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
18 | ||
1da177e4 LT |
19 | #include <linux/kernel.h> |
20 | #include <linux/delay.h> | |
21 | #include <linux/module.h> | |
1da177e4 LT |
22 | #include <linux/init.h> |
23 | #include <linux/parport.h> | |
24 | #include <linux/input.h> | |
72ba9f0c | 25 | #include <linux/mutex.h> |
5a0e3ad6 | 26 | #include <linux/slab.h> |
1da177e4 LT |
27 | |
28 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |
29 | MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); | |
30 | MODULE_LICENSE("GPL"); | |
31 | ||
17dd3f0f DT |
32 | #define GC_MAX_PORTS 3 |
33 | #define GC_MAX_DEVICES 5 | |
1da177e4 | 34 | |
17dd3f0f DT |
35 | struct gc_config { |
36 | int args[GC_MAX_DEVICES + 1]; | |
78167236 | 37 | unsigned int nargs; |
17dd3f0f DT |
38 | }; |
39 | ||
a517e87c | 40 | static struct gc_config gc_cfg[GC_MAX_PORTS]; |
1da177e4 | 41 | |
78167236 | 42 | module_param_array_named(map, gc_cfg[0].args, int, &gc_cfg[0].nargs, 0); |
17dd3f0f | 43 | MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)"); |
78167236 | 44 | module_param_array_named(map2, gc_cfg[1].args, int, &gc_cfg[1].nargs, 0); |
17dd3f0f | 45 | MODULE_PARM_DESC(map2, "Describes second set of devices"); |
78167236 | 46 | module_param_array_named(map3, gc_cfg[2].args, int, &gc_cfg[2].nargs, 0); |
17dd3f0f | 47 | MODULE_PARM_DESC(map3, "Describes third set of devices"); |
1da177e4 | 48 | |
1da177e4 LT |
49 | /* see also gs_psx_delay parameter in PSX support section */ |
50 | ||
0995174d DT |
51 | enum gc_type { |
52 | GC_NONE = 0, | |
53 | GC_SNES, | |
54 | GC_NES, | |
55 | GC_NES4, | |
56 | GC_MULTI, | |
57 | GC_MULTI2, | |
58 | GC_N64, | |
59 | GC_PSX, | |
60 | GC_DDR, | |
61 | GC_SNESMOUSE, | |
62 | GC_MAX | |
63 | }; | |
1da177e4 LT |
64 | |
65 | #define GC_REFRESH_TIME HZ/100 | |
66 | ||
0995174d DT |
67 | struct gc_pad { |
68 | struct input_dev *dev; | |
69 | enum gc_type type; | |
70 | char phys[32]; | |
71 | }; | |
72 | ||
1da177e4 LT |
73 | struct gc { |
74 | struct pardevice *pd; | |
0995174d | 75 | struct gc_pad pads[GC_MAX_DEVICES]; |
1da177e4 | 76 | struct timer_list timer; |
0995174d | 77 | int pad_count[GC_MAX]; |
1da177e4 | 78 | int used; |
a517e87c | 79 | int parportno; |
72ba9f0c | 80 | struct mutex mutex; |
1da177e4 LT |
81 | }; |
82 | ||
7aa9e0e8 SM |
83 | struct gc_subdev { |
84 | unsigned int idx; | |
85 | }; | |
86 | ||
1da177e4 LT |
87 | static struct gc *gc_base[3]; |
88 | ||
af930d64 | 89 | static const int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; |
1da177e4 | 90 | |
af930d64 | 91 | static const char *gc_names[] = { |
d38fcb96 DT |
92 | NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", |
93 | "Multisystem 2-button joystick", "N64 controller", "PSX controller", | |
94 | "PSX DDR controller", "SNES mouse" | |
95 | }; | |
96 | ||
1da177e4 LT |
97 | /* |
98 | * N64 support. | |
99 | */ | |
100 | ||
af930d64 DT |
101 | static const unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 }; |
102 | static const short gc_n64_btn[] = { | |
d38fcb96 DT |
103 | BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, |
104 | BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START | |
105 | }; | |
1da177e4 LT |
106 | |
107 | #define GC_N64_LENGTH 32 /* N64 bit length, not including stop bit */ | |
7aa9e0e8 SM |
108 | #define GC_N64_STOP_LENGTH 5 /* Length of encoded stop bit */ |
109 | #define GC_N64_CMD_00 0x11111111UL | |
110 | #define GC_N64_CMD_01 0xd1111111UL | |
111 | #define GC_N64_CMD_03 0xdd111111UL | |
112 | #define GC_N64_CMD_1b 0xdd1dd111UL | |
113 | #define GC_N64_CMD_c0 0x111111ddUL | |
114 | #define GC_N64_CMD_80 0x1111111dUL | |
115 | #define GC_N64_STOP_BIT 0x1d /* Encoded stop bit */ | |
116 | #define GC_N64_REQUEST_DATA GC_N64_CMD_01 /* the request data command */ | |
1da177e4 | 117 | #define GC_N64_DELAY 133 /* delay between transmit request, and response ready (us) */ |
1da177e4 LT |
118 | #define GC_N64_DWS 3 /* delay between write segments (required for sound playback because of ISA DMA) */ |
119 | /* GC_N64_DWS > 24 is known to fail */ | |
120 | #define GC_N64_POWER_W 0xe2 /* power during write (transmit request) */ | |
121 | #define GC_N64_POWER_R 0xfd /* power during read */ | |
122 | #define GC_N64_OUT 0x1d /* output bits to the 4 pads */ | |
123 | /* Reading the main axes of any N64 pad is known to fail if the corresponding bit */ | |
124 | /* in GC_N64_OUT is pulled low on the output port (by any routine) for more */ | |
125 | /* than 123 us */ | |
126 | #define GC_N64_CLOCK 0x02 /* clock bits for read */ | |
127 | ||
7aa9e0e8 SM |
128 | /* |
129 | * Used for rumble code. | |
130 | */ | |
131 | ||
132 | /* Send encoded command */ | |
133 | static void gc_n64_send_command(struct gc *gc, unsigned long cmd, | |
134 | unsigned char target) | |
135 | { | |
136 | struct parport *port = gc->pd->port; | |
137 | int i; | |
138 | ||
139 | for (i = 0; i < GC_N64_LENGTH; i++) { | |
140 | unsigned char data = (cmd >> i) & 1 ? target : 0; | |
141 | parport_write_data(port, GC_N64_POWER_W | data); | |
142 | udelay(GC_N64_DWS); | |
143 | } | |
144 | } | |
145 | ||
146 | /* Send stop bit */ | |
147 | static void gc_n64_send_stop_bit(struct gc *gc, unsigned char target) | |
148 | { | |
149 | struct parport *port = gc->pd->port; | |
150 | int i; | |
151 | ||
152 | for (i = 0; i < GC_N64_STOP_LENGTH; i++) { | |
153 | unsigned char data = (GC_N64_STOP_BIT >> i) & 1 ? target : 0; | |
154 | parport_write_data(port, GC_N64_POWER_W | data); | |
155 | udelay(GC_N64_DWS); | |
156 | } | |
157 | } | |
158 | ||
1da177e4 LT |
159 | /* |
160 | * gc_n64_read_packet() reads an N64 packet. | |
d38fcb96 DT |
161 | * Each pad uses one bit per byte. So all pads connected to this port |
162 | * are read in parallel. | |
1da177e4 LT |
163 | */ |
164 | ||
165 | static void gc_n64_read_packet(struct gc *gc, unsigned char *data) | |
166 | { | |
167 | int i; | |
168 | unsigned long flags; | |
169 | ||
170 | /* | |
171 | * Request the pad to transmit data | |
172 | */ | |
173 | ||
174 | local_irq_save(flags); | |
7aa9e0e8 SM |
175 | gc_n64_send_command(gc, GC_N64_REQUEST_DATA, GC_N64_OUT); |
176 | gc_n64_send_stop_bit(gc, GC_N64_OUT); | |
1da177e4 LT |
177 | local_irq_restore(flags); |
178 | ||
179 | /* | |
d38fcb96 DT |
180 | * Wait for the pad response to be loaded into the 33-bit register |
181 | * of the adapter. | |
1da177e4 LT |
182 | */ |
183 | ||
184 | udelay(GC_N64_DELAY); | |
185 | ||
186 | /* | |
187 | * Grab data (ignoring the last bit, which is a stop bit) | |
188 | */ | |
189 | ||
190 | for (i = 0; i < GC_N64_LENGTH; i++) { | |
191 | parport_write_data(gc->pd->port, GC_N64_POWER_R); | |
7aa9e0e8 | 192 | udelay(2); |
1da177e4 LT |
193 | data[i] = parport_read_status(gc->pd->port); |
194 | parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK); | |
195 | } | |
196 | ||
197 | /* | |
d38fcb96 DT |
198 | * We must wait 200 ms here for the controller to reinitialize before |
199 | * the next read request. No worries as long as gc_read is polled less | |
200 | * frequently than this. | |
1da177e4 LT |
201 | */ |
202 | ||
203 | } | |
204 | ||
c7fd018d DT |
205 | static void gc_n64_process_packet(struct gc *gc) |
206 | { | |
207 | unsigned char data[GC_N64_LENGTH]; | |
c7fd018d DT |
208 | struct input_dev *dev; |
209 | int i, j, s; | |
d38fcb96 | 210 | signed char x, y; |
c7fd018d DT |
211 | |
212 | gc_n64_read_packet(gc, data); | |
213 | ||
214 | for (i = 0; i < GC_MAX_DEVICES; i++) { | |
215 | ||
0995174d | 216 | if (gc->pads[i].type != GC_N64) |
c7fd018d DT |
217 | continue; |
218 | ||
0995174d | 219 | dev = gc->pads[i].dev; |
c7fd018d DT |
220 | s = gc_status_bit[i]; |
221 | ||
0995174d | 222 | if (s & ~(data[8] | data[9])) { |
c7fd018d | 223 | |
d38fcb96 | 224 | x = y = 0; |
c7fd018d DT |
225 | |
226 | for (j = 0; j < 8; j++) { | |
227 | if (data[23 - j] & s) | |
d38fcb96 | 228 | x |= 1 << j; |
c7fd018d | 229 | if (data[31 - j] & s) |
d38fcb96 | 230 | y |= 1 << j; |
c7fd018d DT |
231 | } |
232 | ||
d38fcb96 DT |
233 | input_report_abs(dev, ABS_X, x); |
234 | input_report_abs(dev, ABS_Y, -y); | |
c7fd018d | 235 | |
d38fcb96 DT |
236 | input_report_abs(dev, ABS_HAT0X, |
237 | !(s & data[6]) - !(s & data[7])); | |
238 | input_report_abs(dev, ABS_HAT0Y, | |
239 | !(s & data[4]) - !(s & data[5])); | |
c7fd018d DT |
240 | |
241 | for (j = 0; j < 10; j++) | |
d38fcb96 DT |
242 | input_report_key(dev, gc_n64_btn[j], |
243 | s & data[gc_n64_bytes[j]]); | |
c7fd018d DT |
244 | |
245 | input_sync(dev); | |
246 | } | |
247 | } | |
248 | } | |
249 | ||
7aa9e0e8 SM |
250 | static int gc_n64_play_effect(struct input_dev *dev, void *data, |
251 | struct ff_effect *effect) | |
252 | { | |
253 | int i; | |
254 | unsigned long flags; | |
255 | struct gc *gc = input_get_drvdata(dev); | |
256 | struct gc_subdev *sdev = data; | |
257 | unsigned char target = 1 << sdev->idx; /* select desired pin */ | |
258 | ||
259 | if (effect->type == FF_RUMBLE) { | |
260 | struct ff_rumble_effect *rumble = &effect->u.rumble; | |
261 | unsigned int cmd = | |
262 | rumble->strong_magnitude || rumble->weak_magnitude ? | |
263 | GC_N64_CMD_01 : GC_N64_CMD_00; | |
264 | ||
265 | local_irq_save(flags); | |
266 | ||
267 | /* Init Rumble - 0x03, 0x80, 0x01, (34)0x80 */ | |
268 | gc_n64_send_command(gc, GC_N64_CMD_03, target); | |
269 | gc_n64_send_command(gc, GC_N64_CMD_80, target); | |
270 | gc_n64_send_command(gc, GC_N64_CMD_01, target); | |
271 | for (i = 0; i < 32; i++) | |
272 | gc_n64_send_command(gc, GC_N64_CMD_80, target); | |
273 | gc_n64_send_stop_bit(gc, target); | |
274 | ||
275 | udelay(GC_N64_DELAY); | |
276 | ||
277 | /* Now start or stop it - 0x03, 0xc0, 0zx1b, (32)0x01/0x00 */ | |
278 | gc_n64_send_command(gc, GC_N64_CMD_03, target); | |
279 | gc_n64_send_command(gc, GC_N64_CMD_c0, target); | |
280 | gc_n64_send_command(gc, GC_N64_CMD_1b, target); | |
281 | for (i = 0; i < 32; i++) | |
282 | gc_n64_send_command(gc, cmd, target); | |
283 | gc_n64_send_stop_bit(gc, target); | |
284 | ||
285 | local_irq_restore(flags); | |
286 | ||
287 | } | |
288 | ||
289 | return 0; | |
290 | } | |
291 | ||
a517e87c | 292 | static int gc_n64_init_ff(struct input_dev *dev, int i) |
7aa9e0e8 SM |
293 | { |
294 | struct gc_subdev *sdev; | |
295 | int err; | |
296 | ||
297 | sdev = kmalloc(sizeof(*sdev), GFP_KERNEL); | |
298 | if (!sdev) | |
299 | return -ENOMEM; | |
300 | ||
301 | sdev->idx = i; | |
302 | ||
303 | input_set_capability(dev, EV_FF, FF_RUMBLE); | |
304 | ||
305 | err = input_ff_create_memless(dev, sdev, gc_n64_play_effect); | |
306 | if (err) { | |
307 | kfree(sdev); | |
308 | return err; | |
309 | } | |
310 | ||
311 | return 0; | |
312 | } | |
313 | ||
1da177e4 LT |
314 | /* |
315 | * NES/SNES support. | |
316 | */ | |
317 | ||
b157d55e RA |
318 | #define GC_NES_DELAY 6 /* Delay between bits - 6us */ |
319 | #define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */ | |
320 | #define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the | |
321 | last 4 bits are unused */ | |
322 | #define GC_SNESMOUSE_LENGTH 32 /* The SNES mouse uses 32 bits, the first | |
323 | 16 bits are equivalent to a gamepad */ | |
1da177e4 LT |
324 | |
325 | #define GC_NES_POWER 0xfc | |
326 | #define GC_NES_CLOCK 0x01 | |
327 | #define GC_NES_LATCH 0x02 | |
328 | ||
af930d64 DT |
329 | static const unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 }; |
330 | static const unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 }; | |
331 | static const short gc_snes_btn[] = { | |
d38fcb96 DT |
332 | BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR |
333 | }; | |
1da177e4 LT |
334 | |
335 | /* | |
336 | * gc_nes_read_packet() reads a NES/SNES packet. | |
337 | * Each pad uses one bit per byte. So all pads connected to | |
338 | * this port are read in parallel. | |
339 | */ | |
340 | ||
341 | static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data) | |
342 | { | |
343 | int i; | |
344 | ||
345 | parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK | GC_NES_LATCH); | |
346 | udelay(GC_NES_DELAY * 2); | |
347 | parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK); | |
348 | ||
349 | for (i = 0; i < length; i++) { | |
350 | udelay(GC_NES_DELAY); | |
351 | parport_write_data(gc->pd->port, GC_NES_POWER); | |
352 | data[i] = parport_read_status(gc->pd->port) ^ 0x7f; | |
353 | udelay(GC_NES_DELAY); | |
354 | parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK); | |
355 | } | |
356 | } | |
357 | ||
c7fd018d DT |
358 | static void gc_nes_process_packet(struct gc *gc) |
359 | { | |
b157d55e | 360 | unsigned char data[GC_SNESMOUSE_LENGTH]; |
0995174d | 361 | struct gc_pad *pad; |
c7fd018d | 362 | struct input_dev *dev; |
b157d55e RA |
363 | int i, j, s, len; |
364 | char x_rel, y_rel; | |
365 | ||
0995174d DT |
366 | len = gc->pad_count[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH : |
367 | (gc->pad_count[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH); | |
c7fd018d | 368 | |
b157d55e | 369 | gc_nes_read_packet(gc, len, data); |
c7fd018d DT |
370 | |
371 | for (i = 0; i < GC_MAX_DEVICES; i++) { | |
372 | ||
0995174d | 373 | pad = &gc->pads[i]; |
7b5d3312 | 374 | dev = pad->dev; |
c7fd018d DT |
375 | s = gc_status_bit[i]; |
376 | ||
0995174d DT |
377 | switch (pad->type) { |
378 | ||
379 | case GC_NES: | |
380 | ||
c7fd018d DT |
381 | input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7])); |
382 | input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5])); | |
c7fd018d | 383 | |
c7fd018d | 384 | for (j = 0; j < 4; j++) |
d38fcb96 DT |
385 | input_report_key(dev, gc_snes_btn[j], |
386 | s & data[gc_nes_bytes[j]]); | |
0995174d DT |
387 | input_sync(dev); |
388 | break; | |
389 | ||
390 | case GC_SNES: | |
391 | ||
392 | input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7])); | |
393 | input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5])); | |
c7fd018d | 394 | |
c7fd018d | 395 | for (j = 0; j < 8; j++) |
d38fcb96 DT |
396 | input_report_key(dev, gc_snes_btn[j], |
397 | s & data[gc_snes_bytes[j]]); | |
0995174d DT |
398 | input_sync(dev); |
399 | break; | |
c7fd018d | 400 | |
0995174d | 401 | case GC_SNESMOUSE: |
b157d55e | 402 | /* |
d38fcb96 DT |
403 | * The 4 unused bits from SNES controllers appear |
404 | * to be ID bits so use them to make sure we are | |
405 | * dealing with a mouse. | |
b157d55e RA |
406 | * gamepad is connected. This is important since |
407 | * my SNES gamepad sends 1's for bits 16-31, which | |
408 | * cause the mouse pointer to quickly move to the | |
409 | * upper left corner of the screen. | |
410 | */ | |
411 | if (!(s & data[12]) && !(s & data[13]) && | |
412 | !(s & data[14]) && (s & data[15])) { | |
413 | input_report_key(dev, BTN_LEFT, s & data[9]); | |
414 | input_report_key(dev, BTN_RIGHT, s & data[8]); | |
415 | ||
416 | x_rel = y_rel = 0; | |
417 | for (j = 0; j < 7; j++) { | |
418 | x_rel <<= 1; | |
419 | if (data[25 + j] & s) | |
420 | x_rel |= 1; | |
421 | ||
422 | y_rel <<= 1; | |
423 | if (data[17 + j] & s) | |
424 | y_rel |= 1; | |
425 | } | |
426 | ||
427 | if (x_rel) { | |
428 | if (data[24] & s) | |
429 | x_rel = -x_rel; | |
430 | input_report_rel(dev, REL_X, x_rel); | |
431 | } | |
432 | ||
433 | if (y_rel) { | |
434 | if (data[16] & s) | |
435 | y_rel = -y_rel; | |
436 | input_report_rel(dev, REL_Y, y_rel); | |
437 | } | |
0995174d DT |
438 | |
439 | input_sync(dev); | |
b157d55e | 440 | } |
0995174d DT |
441 | break; |
442 | ||
443 | default: | |
444 | break; | |
b157d55e | 445 | } |
c7fd018d DT |
446 | } |
447 | } | |
448 | ||
1da177e4 LT |
449 | /* |
450 | * Multisystem joystick support | |
451 | */ | |
452 | ||
453 | #define GC_MULTI_LENGTH 5 /* Multi system joystick packet length is 5 */ | |
454 | #define GC_MULTI2_LENGTH 6 /* One more bit for one more button */ | |
455 | ||
456 | /* | |
457 | * gc_multi_read_packet() reads a Multisystem joystick packet. | |
458 | */ | |
459 | ||
460 | static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data) | |
461 | { | |
462 | int i; | |
463 | ||
464 | for (i = 0; i < length; i++) { | |
465 | parport_write_data(gc->pd->port, ~(1 << i)); | |
466 | data[i] = parport_read_status(gc->pd->port) ^ 0x7f; | |
467 | } | |
468 | } | |
469 | ||
c7fd018d DT |
470 | static void gc_multi_process_packet(struct gc *gc) |
471 | { | |
472 | unsigned char data[GC_MULTI2_LENGTH]; | |
0995174d DT |
473 | int data_len = gc->pad_count[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH; |
474 | struct gc_pad *pad; | |
c7fd018d DT |
475 | struct input_dev *dev; |
476 | int i, s; | |
477 | ||
d38fcb96 | 478 | gc_multi_read_packet(gc, data_len, data); |
c7fd018d DT |
479 | |
480 | for (i = 0; i < GC_MAX_DEVICES; i++) { | |
0995174d DT |
481 | pad = &gc->pads[i]; |
482 | dev = pad->dev; | |
c7fd018d DT |
483 | s = gc_status_bit[i]; |
484 | ||
0995174d DT |
485 | switch (pad->type) { |
486 | case GC_MULTI2: | |
487 | input_report_key(dev, BTN_THUMB, s & data[5]); | |
488 | /* fall through */ | |
489 | ||
490 | case GC_MULTI: | |
d38fcb96 DT |
491 | input_report_abs(dev, ABS_X, |
492 | !(s & data[2]) - !(s & data[3])); | |
493 | input_report_abs(dev, ABS_Y, | |
494 | !(s & data[0]) - !(s & data[1])); | |
c7fd018d | 495 | input_report_key(dev, BTN_TRIGGER, s & data[4]); |
0995174d DT |
496 | input_sync(dev); |
497 | break; | |
c7fd018d | 498 | |
0995174d DT |
499 | default: |
500 | break; | |
501 | } | |
c7fd018d DT |
502 | } |
503 | } | |
504 | ||
1da177e4 LT |
505 | /* |
506 | * PSX support | |
507 | * | |
508 | * See documentation at: | |
631dd1a8 | 509 | * http://www.geocities.co.jp/Playtown/2004/psx/ps_eng.txt |
1da177e4 | 510 | * http://www.gamesx.com/controldata/psxcont/psxcont.htm |
1da177e4 LT |
511 | * |
512 | */ | |
513 | ||
514 | #define GC_PSX_DELAY 25 /* 25 usec */ | |
515 | #define GC_PSX_LENGTH 8 /* talk to the controller in bits */ | |
516 | #define GC_PSX_BYTES 6 /* the maximum number of bytes to read off the controller */ | |
517 | ||
518 | #define GC_PSX_MOUSE 1 /* Mouse */ | |
519 | #define GC_PSX_NEGCON 2 /* NegCon */ | |
520 | #define GC_PSX_NORMAL 4 /* Digital / Analog or Rumble in Digital mode */ | |
521 | #define GC_PSX_ANALOG 5 /* Analog in Analog mode / Rumble in Green mode */ | |
522 | #define GC_PSX_RUMBLE 7 /* Rumble in Red mode */ | |
523 | ||
524 | #define GC_PSX_CLOCK 0x04 /* Pin 4 */ | |
525 | #define GC_PSX_COMMAND 0x01 /* Pin 2 */ | |
526 | #define GC_PSX_POWER 0xf8 /* Pins 5-9 */ | |
527 | #define GC_PSX_SELECT 0x02 /* Pin 3 */ | |
528 | ||
529 | #define GC_PSX_ID(x) ((x) >> 4) /* High nibble is device type */ | |
530 | #define GC_PSX_LEN(x) (((x) & 0xf) << 1) /* Low nibble is length in bytes/2 */ | |
531 | ||
532 | static int gc_psx_delay = GC_PSX_DELAY; | |
533 | module_param_named(psx_delay, gc_psx_delay, uint, 0); | |
534 | MODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)"); | |
535 | ||
af930d64 | 536 | static const short gc_psx_abs[] = { |
d38fcb96 DT |
537 | ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y |
538 | }; | |
af930d64 | 539 | static const short gc_psx_btn[] = { |
d38fcb96 DT |
540 | BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y, |
541 | BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR | |
542 | }; | |
af930d64 | 543 | static const short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 }; |
1da177e4 LT |
544 | |
545 | /* | |
546 | * gc_psx_command() writes 8bit command and reads 8bit data from | |
547 | * the psx pad. | |
548 | */ | |
549 | ||
d38fcb96 | 550 | static void gc_psx_command(struct gc *gc, int b, unsigned char *data) |
1da177e4 | 551 | { |
d38fcb96 | 552 | struct parport *port = gc->pd->port; |
1da177e4 | 553 | int i, j, cmd, read; |
c7fd018d | 554 | |
d38fcb96 | 555 | memset(data, 0, GC_MAX_DEVICES); |
1da177e4 LT |
556 | |
557 | for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) { | |
558 | cmd = (b & 1) ? GC_PSX_COMMAND : 0; | |
d38fcb96 | 559 | parport_write_data(port, cmd | GC_PSX_POWER); |
1da177e4 | 560 | udelay(gc_psx_delay); |
0995174d | 561 | |
d38fcb96 | 562 | read = parport_read_status(port) ^ 0x80; |
0995174d DT |
563 | |
564 | for (j = 0; j < GC_MAX_DEVICES; j++) { | |
c25f7b76 | 565 | struct gc_pad *pad = &gc->pads[j]; |
0995174d DT |
566 | |
567 | if (pad->type == GC_PSX || pad->type == GC_DDR) | |
568 | data[j] |= (read & gc_status_bit[j]) ? (1 << i) : 0; | |
569 | } | |
570 | ||
1da177e4 LT |
571 | parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER); |
572 | udelay(gc_psx_delay); | |
573 | } | |
574 | } | |
575 | ||
576 | /* | |
577 | * gc_psx_read_packet() reads a whole psx packet and returns | |
578 | * device identifier code. | |
579 | */ | |
580 | ||
0995174d DT |
581 | static void gc_psx_read_packet(struct gc *gc, |
582 | unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES], | |
c7fd018d | 583 | unsigned char id[GC_MAX_DEVICES]) |
1da177e4 LT |
584 | { |
585 | int i, j, max_len = 0; | |
586 | unsigned long flags; | |
c7fd018d | 587 | unsigned char data2[GC_MAX_DEVICES]; |
1da177e4 | 588 | |
d38fcb96 DT |
589 | /* Select pad */ |
590 | parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); | |
1da177e4 | 591 | udelay(gc_psx_delay); |
d38fcb96 DT |
592 | /* Deselect, begin command */ |
593 | parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER); | |
1da177e4 LT |
594 | udelay(gc_psx_delay); |
595 | ||
596 | local_irq_save(flags); | |
597 | ||
d38fcb96 DT |
598 | gc_psx_command(gc, 0x01, data2); /* Access pad */ |
599 | gc_psx_command(gc, 0x42, id); /* Get device ids */ | |
600 | gc_psx_command(gc, 0, data2); /* Dump status */ | |
1da177e4 | 601 | |
d38fcb96 | 602 | /* Find the longest pad */ |
0995174d DT |
603 | for (i = 0; i < GC_MAX_DEVICES; i++) { |
604 | struct gc_pad *pad = &gc->pads[i]; | |
605 | ||
606 | if ((pad->type == GC_PSX || pad->type == GC_DDR) && | |
d38fcb96 DT |
607 | GC_PSX_LEN(id[i]) > max_len && |
608 | GC_PSX_LEN(id[i]) <= GC_PSX_BYTES) { | |
1da177e4 | 609 | max_len = GC_PSX_LEN(id[i]); |
d38fcb96 | 610 | } |
0995174d | 611 | } |
1da177e4 | 612 | |
d38fcb96 DT |
613 | /* Read in all the data */ |
614 | for (i = 0; i < max_len; i++) { | |
1da177e4 | 615 | gc_psx_command(gc, 0, data2); |
c7fd018d | 616 | for (j = 0; j < GC_MAX_DEVICES; j++) |
1da177e4 LT |
617 | data[j][i] = data2[j]; |
618 | } | |
619 | ||
620 | local_irq_restore(flags); | |
621 | ||
622 | parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); | |
623 | ||
d38fcb96 DT |
624 | /* Set id's to the real value */ |
625 | for (i = 0; i < GC_MAX_DEVICES; i++) | |
1da177e4 LT |
626 | id[i] = GC_PSX_ID(id[i]); |
627 | } | |
628 | ||
0995174d | 629 | static void gc_psx_report_one(struct gc_pad *pad, unsigned char psx_type, |
d38fcb96 | 630 | unsigned char *data) |
c7fd018d | 631 | { |
0995174d | 632 | struct input_dev *dev = pad->dev; |
d38fcb96 | 633 | int i; |
1da177e4 | 634 | |
0995174d | 635 | switch (psx_type) { |
1da177e4 | 636 | |
d38fcb96 | 637 | case GC_PSX_RUMBLE: |
1da177e4 | 638 | |
d38fcb96 DT |
639 | input_report_key(dev, BTN_THUMBL, ~data[0] & 0x04); |
640 | input_report_key(dev, BTN_THUMBR, ~data[0] & 0x02); | |
c1b433e0 | 641 | /* fall through */ |
1da177e4 | 642 | |
d38fcb96 DT |
643 | case GC_PSX_NEGCON: |
644 | case GC_PSX_ANALOG: | |
1da177e4 | 645 | |
0995174d | 646 | if (pad->type == GC_DDR) { |
d38fcb96 DT |
647 | for (i = 0; i < 4; i++) |
648 | input_report_key(dev, gc_psx_ddr_btn[i], | |
649 | ~data[0] & (0x10 << i)); | |
650 | } else { | |
651 | for (i = 0; i < 4; i++) | |
652 | input_report_abs(dev, gc_psx_abs[i + 2], | |
653 | data[i + 2]); | |
1da177e4 | 654 | |
315543fd DT |
655 | input_report_abs(dev, ABS_X, |
656 | !!(data[0] & 0x80) * 128 + !(data[0] & 0x20) * 127); | |
657 | input_report_abs(dev, ABS_Y, | |
658 | !!(data[0] & 0x10) * 128 + !(data[0] & 0x40) * 127); | |
d38fcb96 | 659 | } |
1da177e4 | 660 | |
d38fcb96 DT |
661 | for (i = 0; i < 8; i++) |
662 | input_report_key(dev, gc_psx_btn[i], ~data[1] & (1 << i)); | |
1da177e4 | 663 | |
d38fcb96 DT |
664 | input_report_key(dev, BTN_START, ~data[0] & 0x08); |
665 | input_report_key(dev, BTN_SELECT, ~data[0] & 0x01); | |
1da177e4 | 666 | |
d38fcb96 | 667 | input_sync(dev); |
1da177e4 | 668 | |
d38fcb96 | 669 | break; |
c7fd018d | 670 | |
d38fcb96 | 671 | case GC_PSX_NORMAL: |
0995174d DT |
672 | |
673 | if (pad->type == GC_DDR) { | |
d38fcb96 DT |
674 | for (i = 0; i < 4; i++) |
675 | input_report_key(dev, gc_psx_ddr_btn[i], | |
676 | ~data[0] & (0x10 << i)); | |
677 | } else { | |
315543fd DT |
678 | input_report_abs(dev, ABS_X, |
679 | !!(data[0] & 0x80) * 128 + !(data[0] & 0x20) * 127); | |
680 | input_report_abs(dev, ABS_Y, | |
681 | !!(data[0] & 0x10) * 128 + !(data[0] & 0x40) * 127); | |
c7fd018d | 682 | |
d38fcb96 DT |
683 | /* |
684 | * For some reason if the extra axes are left unset | |
685 | * they drift. | |
686 | * for (i = 0; i < 4; i++) | |
687 | input_report_abs(dev, gc_psx_abs[i + 2], 128); | |
688 | * This needs to be debugged properly, | |
689 | * maybe fuzz processing needs to be done | |
690 | * in input_sync() | |
691 | * --vojtech | |
692 | */ | |
693 | } | |
c7fd018d | 694 | |
d38fcb96 DT |
695 | for (i = 0; i < 8; i++) |
696 | input_report_key(dev, gc_psx_btn[i], ~data[1] & (1 << i)); | |
c7fd018d | 697 | |
d38fcb96 DT |
698 | input_report_key(dev, BTN_START, ~data[0] & 0x08); |
699 | input_report_key(dev, BTN_SELECT, ~data[0] & 0x01); | |
c7fd018d | 700 | |
d38fcb96 | 701 | input_sync(dev); |
1da177e4 | 702 | |
d38fcb96 | 703 | break; |
1da177e4 | 704 | |
0995174d | 705 | default: /* not a pad, ignore */ |
d38fcb96 DT |
706 | break; |
707 | } | |
708 | } | |
1da177e4 | 709 | |
d38fcb96 DT |
710 | static void gc_psx_process_packet(struct gc *gc) |
711 | { | |
712 | unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES]; | |
713 | unsigned char id[GC_MAX_DEVICES]; | |
0995174d | 714 | struct gc_pad *pad; |
d38fcb96 | 715 | int i; |
1da177e4 | 716 | |
d38fcb96 | 717 | gc_psx_read_packet(gc, data, id); |
c7fd018d | 718 | |
d38fcb96 | 719 | for (i = 0; i < GC_MAX_DEVICES; i++) { |
0995174d DT |
720 | pad = &gc->pads[i]; |
721 | if (pad->type == GC_PSX || pad->type == GC_DDR) | |
722 | gc_psx_report_one(pad, id[i], data[i]); | |
1da177e4 | 723 | } |
c7fd018d | 724 | } |
1da177e4 LT |
725 | |
726 | /* | |
c7fd018d | 727 | * gc_timer() initiates reads of console pads data. |
1da177e4 LT |
728 | */ |
729 | ||
e99e88a9 | 730 | static void gc_timer(struct timer_list *t) |
c7fd018d | 731 | { |
e99e88a9 | 732 | struct gc *gc = from_timer(gc, t, timer); |
1da177e4 | 733 | |
c7fd018d DT |
734 | /* |
735 | * N64 pads - must be read first, any read confuses them for 200 us | |
736 | */ | |
1da177e4 | 737 | |
0995174d | 738 | if (gc->pad_count[GC_N64]) |
c7fd018d | 739 | gc_n64_process_packet(gc); |
1da177e4 | 740 | |
c7fd018d | 741 | /* |
b157d55e | 742 | * NES and SNES pads or mouse |
c7fd018d | 743 | */ |
1da177e4 | 744 | |
0995174d DT |
745 | if (gc->pad_count[GC_NES] || |
746 | gc->pad_count[GC_SNES] || | |
747 | gc->pad_count[GC_SNESMOUSE]) { | |
c7fd018d | 748 | gc_nes_process_packet(gc); |
0995174d | 749 | } |
1da177e4 LT |
750 | |
751 | /* | |
752 | * Multi and Multi2 joysticks | |
753 | */ | |
754 | ||
0995174d | 755 | if (gc->pad_count[GC_MULTI] || gc->pad_count[GC_MULTI2]) |
c7fd018d | 756 | gc_multi_process_packet(gc); |
1da177e4 LT |
757 | |
758 | /* | |
759 | * PSX controllers | |
760 | */ | |
761 | ||
0995174d | 762 | if (gc->pad_count[GC_PSX] || gc->pad_count[GC_DDR]) |
c7fd018d | 763 | gc_psx_process_packet(gc); |
1da177e4 LT |
764 | |
765 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); | |
766 | } | |
767 | ||
768 | static int gc_open(struct input_dev *dev) | |
769 | { | |
8715c1cf | 770 | struct gc *gc = input_get_drvdata(dev); |
8b1a198b DT |
771 | int err; |
772 | ||
72ba9f0c | 773 | err = mutex_lock_interruptible(&gc->mutex); |
8b1a198b DT |
774 | if (err) |
775 | return err; | |
776 | ||
1da177e4 LT |
777 | if (!gc->used++) { |
778 | parport_claim(gc->pd); | |
779 | parport_write_control(gc->pd->port, 0x04); | |
780 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); | |
781 | } | |
8b1a198b | 782 | |
72ba9f0c | 783 | mutex_unlock(&gc->mutex); |
1da177e4 LT |
784 | return 0; |
785 | } | |
786 | ||
787 | static void gc_close(struct input_dev *dev) | |
788 | { | |
8715c1cf | 789 | struct gc *gc = input_get_drvdata(dev); |
8b1a198b | 790 | |
72ba9f0c | 791 | mutex_lock(&gc->mutex); |
1da177e4 | 792 | if (!--gc->used) { |
8b1a198b | 793 | del_timer_sync(&gc->timer); |
1da177e4 LT |
794 | parport_write_control(gc->pd->port, 0x00); |
795 | parport_release(gc->pd); | |
796 | } | |
72ba9f0c | 797 | mutex_unlock(&gc->mutex); |
1da177e4 LT |
798 | } |
799 | ||
a517e87c | 800 | static int gc_setup_pad(struct gc *gc, int idx, int pad_type) |
1da177e4 | 801 | { |
0995174d | 802 | struct gc_pad *pad = &gc->pads[idx]; |
17dd3f0f DT |
803 | struct input_dev *input_dev; |
804 | int i; | |
7aa9e0e8 | 805 | int err; |
1da177e4 | 806 | |
5bc923c5 | 807 | if (pad_type < 1 || pad_type >= GC_MAX) { |
a1e12747 | 808 | pr_err("Pad type %d unknown\n", pad_type); |
17dd3f0f | 809 | return -EINVAL; |
1da177e4 LT |
810 | } |
811 | ||
0995174d | 812 | pad->dev = input_dev = input_allocate_device(); |
17dd3f0f | 813 | if (!input_dev) { |
a1e12747 | 814 | pr_err("Not enough memory for input device\n"); |
17dd3f0f | 815 | return -ENOMEM; |
1da177e4 LT |
816 | } |
817 | ||
0995174d DT |
818 | pad->type = pad_type; |
819 | ||
820 | snprintf(pad->phys, sizeof(pad->phys), | |
821 | "%s/input%d", gc->pd->port->name, idx); | |
822 | ||
17dd3f0f | 823 | input_dev->name = gc_names[pad_type]; |
0995174d | 824 | input_dev->phys = pad->phys; |
17dd3f0f DT |
825 | input_dev->id.bustype = BUS_PARPORT; |
826 | input_dev->id.vendor = 0x0001; | |
827 | input_dev->id.product = pad_type; | |
828 | input_dev->id.version = 0x0100; | |
8715c1cf DT |
829 | |
830 | input_set_drvdata(input_dev, gc); | |
17dd3f0f DT |
831 | |
832 | input_dev->open = gc_open; | |
833 | input_dev->close = gc_close; | |
834 | ||
b157d55e | 835 | if (pad_type != GC_SNESMOUSE) { |
7b19ada2 | 836 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
17dd3f0f | 837 | |
b157d55e RA |
838 | for (i = 0; i < 2; i++) |
839 | input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0); | |
840 | } else | |
7b19ada2 | 841 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); |
17dd3f0f | 842 | |
0995174d | 843 | gc->pad_count[pad_type]++; |
17dd3f0f DT |
844 | |
845 | switch (pad_type) { | |
846 | ||
d38fcb96 DT |
847 | case GC_N64: |
848 | for (i = 0; i < 10; i++) | |
a5a45b7f | 849 | input_set_capability(input_dev, EV_KEY, gc_n64_btn[i]); |
b157d55e | 850 | |
d38fcb96 DT |
851 | for (i = 0; i < 2; i++) { |
852 | input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2); | |
853 | input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); | |
854 | } | |
17dd3f0f | 855 | |
d38fcb96 DT |
856 | err = gc_n64_init_ff(input_dev, idx); |
857 | if (err) { | |
fef5f569 JP |
858 | pr_warn("Failed to initiate rumble for N64 device %d\n", |
859 | idx); | |
0995174d | 860 | goto err_free_dev; |
d38fcb96 | 861 | } |
17dd3f0f | 862 | |
d38fcb96 DT |
863 | break; |
864 | ||
865 | case GC_SNESMOUSE: | |
a5a45b7f MF |
866 | input_set_capability(input_dev, EV_KEY, BTN_LEFT); |
867 | input_set_capability(input_dev, EV_KEY, BTN_RIGHT); | |
868 | input_set_capability(input_dev, EV_REL, REL_X); | |
869 | input_set_capability(input_dev, EV_REL, REL_Y); | |
d38fcb96 DT |
870 | break; |
871 | ||
872 | case GC_SNES: | |
873 | for (i = 4; i < 8; i++) | |
a5a45b7f | 874 | input_set_capability(input_dev, EV_KEY, gc_snes_btn[i]); |
c1b433e0 | 875 | /* fall through */ |
d38fcb96 DT |
876 | case GC_NES: |
877 | for (i = 0; i < 4; i++) | |
a5a45b7f | 878 | input_set_capability(input_dev, EV_KEY, gc_snes_btn[i]); |
d38fcb96 DT |
879 | break; |
880 | ||
881 | case GC_MULTI2: | |
a5a45b7f | 882 | input_set_capability(input_dev, EV_KEY, BTN_THUMB); |
c1b433e0 | 883 | /* fall through */ |
d38fcb96 | 884 | case GC_MULTI: |
a5a45b7f MF |
885 | input_set_capability(input_dev, EV_KEY, BTN_TRIGGER); |
886 | /* fall through */ | |
d38fcb96 DT |
887 | break; |
888 | ||
889 | case GC_PSX: | |
890 | for (i = 0; i < 6; i++) | |
891 | input_set_abs_params(input_dev, | |
892 | gc_psx_abs[i], 4, 252, 0, 2); | |
893 | for (i = 0; i < 12; i++) | |
a5a45b7f MF |
894 | input_set_capability(input_dev, EV_KEY, gc_psx_btn[i]); |
895 | break; | |
d38fcb96 DT |
896 | |
897 | break; | |
898 | ||
899 | case GC_DDR: | |
900 | for (i = 0; i < 4; i++) | |
a5a45b7f MF |
901 | input_set_capability(input_dev, EV_KEY, |
902 | gc_psx_ddr_btn[i]); | |
d38fcb96 | 903 | for (i = 0; i < 12; i++) |
a5a45b7f | 904 | input_set_capability(input_dev, EV_KEY, gc_psx_btn[i]); |
d38fcb96 DT |
905 | |
906 | break; | |
1da177e4 | 907 | } |
8b1a198b | 908 | |
0995174d DT |
909 | err = input_register_device(pad->dev); |
910 | if (err) | |
911 | goto err_free_dev; | |
912 | ||
17dd3f0f | 913 | return 0; |
0995174d DT |
914 | |
915 | err_free_dev: | |
916 | input_free_device(pad->dev); | |
917 | pad->dev = NULL; | |
918 | return err; | |
17dd3f0f | 919 | } |
1da177e4 | 920 | |
a517e87c | 921 | static void gc_attach(struct parport *pp) |
17dd3f0f DT |
922 | { |
923 | struct gc *gc; | |
17dd3f0f | 924 | struct pardevice *pd; |
c36906c5 | 925 | int i, port_idx; |
0995174d | 926 | int count = 0; |
a517e87c SM |
927 | int *pads, n_pads; |
928 | struct pardev_cb gc_parport_cb; | |
929 | ||
c36906c5 SM |
930 | for (port_idx = 0; port_idx < GC_MAX_PORTS; port_idx++) { |
931 | if (gc_cfg[port_idx].nargs == 0 || gc_cfg[port_idx].args[0] < 0) | |
a517e87c SM |
932 | continue; |
933 | ||
c36906c5 | 934 | if (gc_cfg[port_idx].args[0] == pp->number) |
a517e87c SM |
935 | break; |
936 | } | |
1da177e4 | 937 | |
c36906c5 | 938 | if (port_idx == GC_MAX_PORTS) { |
a517e87c SM |
939 | pr_debug("Not using parport%d.\n", pp->number); |
940 | return; | |
17dd3f0f | 941 | } |
c36906c5 SM |
942 | pads = gc_cfg[port_idx].args + 1; |
943 | n_pads = gc_cfg[port_idx].nargs - 1; | |
a517e87c | 944 | |
eb12a5f5 | 945 | memset(&gc_parport_cb, 0, sizeof(gc_parport_cb)); |
a517e87c | 946 | gc_parport_cb.flags = PARPORT_FLAG_EXCL; |
1da177e4 | 947 | |
c36906c5 SM |
948 | pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb, |
949 | port_idx); | |
17dd3f0f | 950 | if (!pd) { |
a1e12747 | 951 | pr_err("parport busy already - lp.o loaded?\n"); |
a517e87c | 952 | return; |
1da177e4 LT |
953 | } |
954 | ||
17dd3f0f DT |
955 | gc = kzalloc(sizeof(struct gc), GFP_KERNEL); |
956 | if (!gc) { | |
a1e12747 | 957 | pr_err("Not enough memory\n"); |
17dd3f0f DT |
958 | goto err_unreg_pardev; |
959 | } | |
1da177e4 | 960 | |
72ba9f0c | 961 | mutex_init(&gc->mutex); |
17dd3f0f | 962 | gc->pd = pd; |
a517e87c | 963 | gc->parportno = pp->number; |
e99e88a9 | 964 | timer_setup(&gc->timer, gc_timer, 0); |
1da177e4 | 965 | |
c7fd018d | 966 | for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) { |
17dd3f0f | 967 | if (!pads[i]) |
1da177e4 LT |
968 | continue; |
969 | ||
a517e87c | 970 | if (gc_setup_pad(gc, i, pads[i])) |
77fc46ca | 971 | goto err_unreg_devs; |
1da177e4 | 972 | |
0995174d | 973 | count++; |
17dd3f0f | 974 | } |
1da177e4 | 975 | |
0995174d | 976 | if (count == 0) { |
a1e12747 | 977 | pr_err("No valid devices specified\n"); |
17dd3f0f DT |
978 | goto err_free_gc; |
979 | } | |
1da177e4 | 980 | |
c36906c5 | 981 | gc_base[port_idx] = gc; |
a517e87c | 982 | return; |
1da177e4 | 983 | |
77fc46ca | 984 | err_unreg_devs: |
17dd3f0f | 985 | while (--i >= 0) |
0995174d DT |
986 | if (gc->pads[i].dev) |
987 | input_unregister_device(gc->pads[i].dev); | |
17dd3f0f DT |
988 | err_free_gc: |
989 | kfree(gc); | |
990 | err_unreg_pardev: | |
991 | parport_unregister_device(pd); | |
17dd3f0f | 992 | } |
1da177e4 | 993 | |
a517e87c | 994 | static void gc_detach(struct parport *port) |
17dd3f0f DT |
995 | { |
996 | int i; | |
a517e87c SM |
997 | struct gc *gc; |
998 | ||
999 | for (i = 0; i < GC_MAX_PORTS; i++) { | |
1000 | if (gc_base[i] && gc_base[i]->parportno == port->number) | |
1001 | break; | |
1002 | } | |
1003 | ||
1004 | if (i == GC_MAX_PORTS) | |
1005 | return; | |
1006 | ||
1007 | gc = gc_base[i]; | |
1008 | gc_base[i] = NULL; | |
1da177e4 | 1009 | |
17dd3f0f | 1010 | for (i = 0; i < GC_MAX_DEVICES; i++) |
0995174d DT |
1011 | if (gc->pads[i].dev) |
1012 | input_unregister_device(gc->pads[i].dev); | |
17dd3f0f DT |
1013 | parport_unregister_device(gc->pd); |
1014 | kfree(gc); | |
1015 | } | |
1da177e4 | 1016 | |
a517e87c SM |
1017 | static struct parport_driver gc_parport_driver = { |
1018 | .name = "gamecon", | |
1019 | .match_port = gc_attach, | |
1020 | .detach = gc_detach, | |
1021 | .devmodel = true, | |
1022 | }; | |
1023 | ||
17dd3f0f DT |
1024 | static int __init gc_init(void) |
1025 | { | |
1026 | int i; | |
1027 | int have_dev = 0; | |
1da177e4 | 1028 | |
17dd3f0f | 1029 | for (i = 0; i < GC_MAX_PORTS; i++) { |
78167236 | 1030 | if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0) |
17dd3f0f | 1031 | continue; |
1da177e4 | 1032 | |
78167236 | 1033 | if (gc_cfg[i].nargs < 2) { |
a1e12747 | 1034 | pr_err("at least one device must be specified\n"); |
a517e87c | 1035 | return -EINVAL; |
17dd3f0f | 1036 | } |
1da177e4 | 1037 | |
17dd3f0f | 1038 | have_dev = 1; |
1da177e4 LT |
1039 | } |
1040 | ||
a517e87c SM |
1041 | if (!have_dev) |
1042 | return -ENODEV; | |
1da177e4 | 1043 | |
a517e87c | 1044 | return parport_register_driver(&gc_parport_driver); |
1da177e4 LT |
1045 | } |
1046 | ||
1047 | static void __exit gc_exit(void) | |
1048 | { | |
a517e87c | 1049 | parport_unregister_driver(&gc_parport_driver); |
1da177e4 LT |
1050 | } |
1051 | ||
1052 | module_init(gc_init); | |
1053 | module_exit(gc_exit); |