blob: 573191dd78e8c9e7e54f44546501c785b21c79e4 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * Driver for the Gravis Grip Multiport, a gamepad "hub" that
3 * connects up to four 9-pin digital gamepads/joysticks.
4 * Driver tested on SMP and UP kernel versions 2.4.18-4 and 2.4.18-5.
5 *
6 * Thanks to Chris Gassib for helpful advice.
7 *
8 * Copyright (c) 2002 Brian Bonnlander, Bill Soudan
9 * Copyright (c) 1998-2000 Vojtech Pavlik
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/slab.h>
15#include <linux/gameport.h>
16#include <linux/input.h>
17#include <linux/delay.h>
18#include <linux/proc_fs.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -080019#include <linux/jiffies.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
21#define DRIVER_DESC "Gravis Grip Multiport driver"
22
23MODULE_AUTHOR("Brian Bonnlander");
24MODULE_DESCRIPTION(DRIVER_DESC);
25MODULE_LICENSE("GPL");
26
27#ifdef GRIP_DEBUG
28#define dbg(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg)
29#else
30#define dbg(format, arg...) do {} while (0)
31#endif
32
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -050033#define GRIP_MAX_PORTS 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070034/*
35 * Grip multiport state
36 */
37
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -050038struct grip_port {
39 struct input_dev *dev;
40 int mode;
41 int registered;
42
43 /* individual gamepad states */
44 int buttons;
45 int xaxes;
46 int yaxes;
47 int dirty; /* has the state been updated? */
48};
49
Linus Torvalds1da177e2005-04-16 15:20:36 -070050struct grip_mp {
51 struct gameport *gameport;
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -050052 struct grip_port *port[GRIP_MAX_PORTS];
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 int reads;
54 int bads;
Linus Torvalds1da177e2005-04-16 15:20:36 -070055};
56
57/*
58 * Multiport packet interpretation
59 */
60
61#define PACKET_FULL 0x80000000 /* packet is full */
62#define PACKET_IO_FAST 0x40000000 /* 3 bits per gameport read */
63#define PACKET_IO_SLOW 0x20000000 /* 1 bit per gameport read */
64#define PACKET_MP_MORE 0x04000000 /* multiport wants to send more */
65#define PACKET_MP_DONE 0x02000000 /* multiport done sending */
66
67/*
68 * Packet status code interpretation
69 */
70
71#define IO_GOT_PACKET 0x0100 /* Got a packet */
72#define IO_MODE_FAST 0x0200 /* Used 3 data bits per gameport read */
73#define IO_SLOT_CHANGE 0x0800 /* Multiport physical slot status changed */
74#define IO_DONE 0x1000 /* Multiport is done sending packets */
75#define IO_RETRY 0x4000 /* Try again later to get packet */
76#define IO_RESET 0x8000 /* Force multiport to resend all packets */
77
78/*
79 * Gamepad configuration data. Other 9-pin digital joystick devices
80 * may work with the multiport, so this may not be an exhaustive list!
81 * Commodore 64 joystick remains untested.
82 */
83
84#define GRIP_INIT_DELAY 2000 /* 2 ms */
85
86#define GRIP_MODE_NONE 0
87#define GRIP_MODE_RESET 1
88#define GRIP_MODE_GP 2
89#define GRIP_MODE_C64 3
90
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -050091static const int grip_btn_gp[] = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
92static const int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -050094static const int grip_abs_gp[] = { ABS_X, ABS_Y, -1 };
95static const int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -050097static const int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
98static const int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500100static const char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
102static const int init_seq[] = {
103 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
104 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
105 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
106 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1 };
107
108/* Maps multiport directional values to X,Y axis values (each axis encoded in 3 bits) */
109
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500110static const int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500112static int register_slot(int i, struct grip_mp *grip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
114/*
115 * Returns whether an odd or even number of bits are on in pkt.
116 */
117
118static int bit_parity(u32 pkt)
119{
120 int x = pkt ^ (pkt >> 16);
121 x ^= x >> 8;
122 x ^= x >> 4;
123 x ^= x >> 2;
124 x ^= x >> 1;
125 return x & 1;
126}
127
128/*
129 * Poll gameport; return true if all bits set in 'onbits' are on and
130 * all bits set in 'offbits' are off.
131 */
132
133static inline int poll_until(u8 onbits, u8 offbits, int u_sec, struct gameport* gp, u8 *data)
134{
135 int i, nloops;
136
137 nloops = gameport_time(gp, u_sec);
138 for (i = 0; i < nloops; i++) {
139 *data = gameport_read(gp);
140 if ((*data & onbits) == onbits &&
141 (~(*data) & offbits) == offbits)
142 return 1;
143 }
144 dbg("gameport timed out after %d microseconds.\n", u_sec);
145 return 0;
146}
147
148/*
149 * Gets a 28-bit packet from the multiport.
150 *
151 * After getting a packet successfully, commands encoded by sendcode may
152 * be sent to the multiport.
153 *
154 * The multiport clock value is reflected in gameport bit B4.
155 *
156 * Returns a packet status code indicating whether packet is valid, the transfer
157 * mode, and any error conditions.
158 *
159 * sendflags: current I/O status
160 * sendcode: data to send to the multiport if sendflags is nonzero
161 */
162
163static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *packet)
164{
165 u8 raw_data; /* raw data from gameport */
166 u8 data_mask; /* packet data bits from raw_data */
167 u32 pkt; /* packet temporary storage */
168 int bits_per_read; /* num packet bits per gameport read */
169 int portvals = 0; /* used for port value sanity check */
170 int i;
171
172 /* Gameport bits B0, B4, B5 should first be off, then B4 should come on. */
173
174 *packet = 0;
175 raw_data = gameport_read(gameport);
176 if (raw_data & 1)
Dmitry Torokhovab0c3442005-05-29 02:28:55 -0500177 return IO_RETRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178
179 for (i = 0; i < 64; i++) {
180 raw_data = gameport_read(gameport);
181 portvals |= 1 << ((raw_data >> 4) & 3); /* Demux B4, B5 */
182 }
183
184 if (portvals == 1) { /* B4, B5 off */
185 raw_data = gameport_read(gameport);
186 portvals = raw_data & 0xf0;
187
188 if (raw_data & 0x31)
189 return IO_RESET;
190 gameport_trigger(gameport);
191
192 if (!poll_until(0x10, 0, 308, gameport, &raw_data))
193 return IO_RESET;
194 } else
195 return IO_RETRY;
196
197 /* Determine packet transfer mode and prepare for packet construction. */
198
199 if (raw_data & 0x20) { /* 3 data bits/read */
200 portvals |= raw_data >> 4; /* Compare B4-B7 before & after trigger */
201
202 if (portvals != 0xb)
203 return 0;
204 data_mask = 7;
205 bits_per_read = 3;
206 pkt = (PACKET_FULL | PACKET_IO_FAST) >> 28;
207 } else { /* 1 data bit/read */
208 data_mask = 1;
209 bits_per_read = 1;
210 pkt = (PACKET_FULL | PACKET_IO_SLOW) >> 28;
211 }
212
213 /* Construct a packet. Final data bits must be zero. */
214
215 while (1) {
216 if (!poll_until(0, 0x10, 77, gameport, &raw_data))
217 return IO_RESET;
218 raw_data = (raw_data >> 5) & data_mask;
219
220 if (pkt & PACKET_FULL)
221 break;
222 pkt = (pkt << bits_per_read) | raw_data;
223
224 if (!poll_until(0x10, 0, 77, gameport, &raw_data))
225 return IO_RESET;
226 }
227
228 if (raw_data)
229 return IO_RESET;
230
231 /* If 3 bits/read used, drop from 30 bits to 28. */
232
233 if (bits_per_read == 3) {
234 pkt = (pkt & 0xffff0000) | ((pkt << 1) & 0xffff);
235 pkt = (pkt >> 2) | 0xf0000000;
236 }
237
238 if (bit_parity(pkt) == 1)
239 return IO_RESET;
240
241 /* Acknowledge packet receipt */
242
243 if (!poll_until(0x30, 0, 77, gameport, &raw_data))
244 return IO_RESET;
245
246 raw_data = gameport_read(gameport);
247
248 if (raw_data & 1)
249 return IO_RESET;
250
251 gameport_trigger(gameport);
252
253 if (!poll_until(0, 0x20, 77, gameport, &raw_data))
254 return IO_RESET;
255
256 /* Return if we just wanted the packet or multiport wants to send more */
257
258 *packet = pkt;
259 if ((sendflags == 0) || ((sendflags & IO_RETRY) && !(pkt & PACKET_MP_DONE)))
260 return IO_GOT_PACKET;
261
262 if (pkt & PACKET_MP_MORE)
263 return IO_GOT_PACKET | IO_RETRY;
264
265 /* Multiport is done sending packets and is ready to receive data */
266
267 if (!poll_until(0x20, 0, 77, gameport, &raw_data))
268 return IO_GOT_PACKET | IO_RESET;
269
270 raw_data = gameport_read(gameport);
271 if (raw_data & 1)
272 return IO_GOT_PACKET | IO_RESET;
273
274 /* Trigger gameport based on bits in sendcode */
275
276 gameport_trigger(gameport);
277 do {
278 if (!poll_until(0x20, 0x10, 116, gameport, &raw_data))
279 return IO_GOT_PACKET | IO_RESET;
280
281 if (!poll_until(0x30, 0, 193, gameport, &raw_data))
282 return IO_GOT_PACKET | IO_RESET;
283
284 if (raw_data & 1)
285 return IO_GOT_PACKET | IO_RESET;
286
287 if (sendcode & 1)
288 gameport_trigger(gameport);
289
290 sendcode >>= 1;
291 } while (sendcode);
292
293 return IO_GOT_PACKET | IO_MODE_FAST;
294}
295
296/*
297 * Disables and restores interrupts for mp_io(), which does the actual I/O.
298 */
299
300static int multiport_io(struct gameport* gameport, int sendflags, int sendcode, u32 *packet)
301{
302 int status;
303 unsigned long flags;
304
305 local_irq_save(flags);
306 status = mp_io(gameport, sendflags, sendcode, packet);
307 local_irq_restore(flags);
308
309 return status;
310}
311
312/*
313 * Puts multiport into digital mode. Multiport LED turns green.
314 *
315 * Returns true if a valid digital packet was received, false otherwise.
316 */
317
318static int dig_mode_start(struct gameport *gameport, u32 *packet)
319{
Andi Drebes5ec1f7f2007-06-14 23:33:01 -0400320 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 int flags, tries = 0, bads = 0;
322
Andi Drebes5ec1f7f2007-06-14 23:33:01 -0400323 for (i = 0; i < ARRAY_SIZE(init_seq); i++) { /* Send magic sequence */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 if (init_seq[i])
325 gameport_trigger(gameport);
326 udelay(GRIP_INIT_DELAY);
327 }
328
329 for (i = 0; i < 16; i++) /* Wait for multiport to settle */
330 udelay(GRIP_INIT_DELAY);
331
332 while (tries < 64 && bads < 8) { /* Reset multiport and try getting a packet */
333
334 flags = multiport_io(gameport, IO_RESET, 0x27, packet);
335
336 if (flags & IO_MODE_FAST)
337 return 1;
338
339 if (flags & IO_RETRY)
340 tries++;
341 else
342 bads++;
343 }
344 return 0;
345}
346
347/*
348 * Packet structure: B0-B15 => gamepad state
349 * B16-B20 => gamepad device type
350 * B21-B24 => multiport slot index (1-4)
351 *
352 * Known device types: 0x1f (grip pad), 0x0 (no device). Others may exist.
353 *
354 * Returns the packet status.
355 */
356
357static int get_and_decode_packet(struct grip_mp *grip, int flags)
358{
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500359 struct grip_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 u32 packet;
361 int joytype = 0;
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500362 int slot;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
364 /* Get a packet and check for validity */
365
366 flags &= IO_RESET | IO_RETRY;
367 flags = multiport_io(grip->gameport, flags, 0, &packet);
368 grip->reads++;
369
370 if (packet & PACKET_MP_DONE)
371 flags |= IO_DONE;
372
373 if (flags && !(flags & IO_GOT_PACKET)) {
374 grip->bads++;
375 return flags;
376 }
377
378 /* Ignore non-gamepad packets, e.g. multiport hardware version */
379
380 slot = ((packet >> 21) & 0xf) - 1;
381 if ((slot < 0) || (slot > 3))
382 return flags;
383
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500384 port = grip->port[slot];
385
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 /*
387 * Handle "reset" packets, which occur at startup, and when gamepads
388 * are removed or plugged in. May contain configuration of a new gamepad.
389 */
390
391 joytype = (packet >> 16) & 0x1f;
392 if (!joytype) {
393
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500394 if (port->registered) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 printk(KERN_INFO "grip_mp: removing %s, slot %d\n",
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500396 grip_name[port->mode], slot);
397 input_unregister_device(port->dev);
398 port->registered = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 }
400 dbg("Reset: grip multiport slot %d\n", slot);
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500401 port->mode = GRIP_MODE_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 flags |= IO_SLOT_CHANGE;
403 return flags;
404 }
405
406 /* Interpret a grip pad packet */
407
408 if (joytype == 0x1f) {
409
410 int dir = (packet >> 8) & 0xf; /* eight way directional value */
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500411 port->buttons = (~packet) & 0xff;
412 port->yaxes = ((axis_map[dir] >> 2) & 3) - 1;
413 port->xaxes = (axis_map[dir] & 3) - 1;
414 port->dirty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500416 if (port->mode == GRIP_MODE_RESET)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 flags |= IO_SLOT_CHANGE;
418
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500419 port->mode = GRIP_MODE_GP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500421 if (!port->registered) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 dbg("New Grip pad in multiport slot %d.\n", slot);
Dmitry Torokhov127278c2006-11-05 22:40:09 -0500423 if (register_slot(slot, grip)) {
424 port->mode = GRIP_MODE_RESET;
425 port->dirty = 0;
426 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 }
428 return flags;
429 }
430
431 /* Handle non-grip device codes. For now, just print diagnostics. */
432
433 {
434 static int strange_code = 0;
435 if (strange_code != joytype) {
436 printk(KERN_INFO "Possible non-grip pad/joystick detected.\n");
437 printk(KERN_INFO "Got joy type 0x%x and packet 0x%x.\n", joytype, packet);
438 strange_code = joytype;
439 }
440 }
441 return flags;
442}
443
444/*
445 * Returns true if all multiport slot states appear valid.
446 */
447
448static int slots_valid(struct grip_mp *grip)
449{
450 int flags, slot, invalid = 0, active = 0;
451
452 flags = get_and_decode_packet(grip, 0);
453 if (!(flags & IO_GOT_PACKET))
454 return 0;
455
456 for (slot = 0; slot < 4; slot++) {
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500457 if (grip->port[slot]->mode == GRIP_MODE_RESET)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 invalid = 1;
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500459 if (grip->port[slot]->mode != GRIP_MODE_NONE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 active = 1;
461 }
462
463 /* Return true if no active slot but multiport sent all its data */
464 if (!active)
465 return (flags & IO_DONE) ? 1 : 0;
466
467 /* Return false if invalid device code received */
468 return invalid ? 0 : 1;
469}
470
471/*
472 * Returns whether the multiport was placed into digital mode and
473 * able to communicate its state successfully.
474 */
475
476static int multiport_init(struct grip_mp *grip)
477{
478 int dig_mode, initialized = 0, tries = 0;
479 u32 packet;
480
481 dig_mode = dig_mode_start(grip->gameport, &packet);
482 while (!dig_mode && tries < 4) {
483 dig_mode = dig_mode_start(grip->gameport, &packet);
484 tries++;
485 }
486
487 if (dig_mode)
488 dbg("multiport_init(): digital mode activated.\n");
489 else {
490 dbg("multiport_init(): unable to activate digital mode.\n");
491 return 0;
492 }
493
494 /* Get packets, store multiport state, and check state's validity */
495 for (tries = 0; tries < 4096; tries++) {
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500496 if (slots_valid(grip)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 initialized = 1;
498 break;
499 }
500 }
501 dbg("multiport_init(): initialized == %d\n", initialized);
502 return initialized;
503}
504
505/*
506 * Reports joystick state to the linux input layer.
507 */
508
509static void report_slot(struct grip_mp *grip, int slot)
510{
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500511 struct grip_port *port = grip->port[slot];
512 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
514 /* Store button states with linux input driver */
515
516 for (i = 0; i < 8; i++)
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500517 input_report_key(port->dev, grip_btn_gp[i], (port->buttons >> i) & 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518
519 /* Store axis states with linux driver */
520
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500521 input_report_abs(port->dev, ABS_X, port->xaxes);
522 input_report_abs(port->dev, ABS_Y, port->yaxes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
524 /* Tell the receiver of the events to process them */
525
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500526 input_sync(port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500528 port->dirty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529}
530
531/*
532 * Get the multiport state.
533 */
534
535static void grip_poll(struct gameport *gameport)
536{
537 struct grip_mp *grip = gameport_get_drvdata(gameport);
538 int i, npkts, flags;
539
540 for (npkts = 0; npkts < 4; npkts++) {
541 flags = IO_RETRY;
542 for (i = 0; i < 32; i++) {
543 flags = get_and_decode_packet(grip, flags);
544 if ((flags & IO_GOT_PACKET) || !(flags & IO_RETRY))
545 break;
546 }
547 if (flags & IO_DONE)
548 break;
549 }
550
551 for (i = 0; i < 4; i++)
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500552 if (grip->port[i]->dirty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 report_slot(grip, i);
554}
555
556/*
557 * Called when a joystick device file is opened
558 */
559
560static int grip_open(struct input_dev *dev)
561{
Dmitry Torokhov8715c1c2007-04-12 01:34:14 -0400562 struct grip_mp *grip = input_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
564 gameport_start_polling(grip->gameport);
565 return 0;
566}
567
568/*
569 * Called when a joystick device file is closed
570 */
571
572static void grip_close(struct input_dev *dev)
573{
Dmitry Torokhov8715c1c2007-04-12 01:34:14 -0400574 struct grip_mp *grip = input_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
Dmitry Torokhov8715c1c2007-04-12 01:34:14 -0400576 gameport_stop_polling(grip->gameport);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577}
578
579/*
580 * Tell the linux input layer about a newly plugged-in gamepad.
581 */
582
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500583static int register_slot(int slot, struct grip_mp *grip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584{
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500585 struct grip_port *port = grip->port[slot];
586 struct input_dev *input_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 int j, t;
Dmitry Torokhov127278c2006-11-05 22:40:09 -0500588 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500590 port->dev = input_dev = input_allocate_device();
591 if (!input_dev)
592 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500594 input_dev->name = grip_name[port->mode];
595 input_dev->id.bustype = BUS_GAMEPORT;
596 input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
597 input_dev->id.product = 0x0100 + port->mode;
598 input_dev->id.version = 0x0100;
Dmitry Torokhov935e6582007-04-12 01:35:26 -0400599 input_dev->dev.parent = &grip->gameport->dev;
Dmitry Torokhov8715c1c2007-04-12 01:34:14 -0400600
601 input_set_drvdata(input_dev, grip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500603 input_dev->open = grip_open;
604 input_dev->close = grip_close;
605
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700606 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500607
608 for (j = 0; (t = grip_abs[port->mode][j]) >= 0; j++)
609 input_set_abs_params(input_dev, t, -1, 1, 0, 0);
610
611 for (j = 0; (t = grip_btn[port->mode][j]) >= 0; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 if (t > 0)
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500613 set_bit(t, input_dev->keybit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Dmitry Torokhov127278c2006-11-05 22:40:09 -0500615 err = input_register_device(port->dev);
616 if (err) {
617 input_free_device(port->dev);
618 return err;
619 }
620
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500621 port->registered = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500623 if (port->dirty) /* report initial state, if any */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 report_slot(grip, slot);
625
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500626 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627}
628
629static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
630{
631 struct grip_mp *grip;
632 int err;
633
Pekka Enberga97e1482005-09-06 15:18:33 -0700634 if (!(grip = kzalloc(sizeof(struct grip_mp), GFP_KERNEL)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 return -ENOMEM;
636
637 grip->gameport = gameport;
638
639 gameport_set_drvdata(gameport, grip);
640
641 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
642 if (err)
643 goto fail1;
644
645 gameport_set_poll_handler(gameport, grip_poll);
646 gameport_set_poll_interval(gameport, 20);
647
648 if (!multiport_init(grip)) {
649 err = -ENODEV;
650 goto fail2;
651 }
652
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500653 if (!grip->port[0]->mode && !grip->port[1]->mode && !grip->port[2]->mode && !grip->port[3]->mode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 /* nothing plugged in */
655 err = -ENODEV;
656 goto fail2;
657 }
658
659 return 0;
660
661fail2: gameport_close(gameport);
662fail1: gameport_set_drvdata(gameport, NULL);
663 kfree(grip);
664 return err;
665}
666
667static void grip_disconnect(struct gameport *gameport)
668{
669 struct grip_mp *grip = gameport_get_drvdata(gameport);
670 int i;
671
672 for (i = 0; i < 4; i++)
Dmitry Torokhov17dd3f02005-09-15 02:01:52 -0500673 if (grip->port[i]->registered)
674 input_unregister_device(grip->port[i]->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 gameport_close(gameport);
676 gameport_set_drvdata(gameport, NULL);
677 kfree(grip);
678}
679
680static struct gameport_driver grip_drv = {
681 .driver = {
682 .name = "grip_mp",
683 },
684 .description = DRIVER_DESC,
685 .connect = grip_connect,
686 .disconnect = grip_disconnect,
687};
688
Axel Lin98a84132012-04-03 23:52:27 -0700689module_gameport_driver(grip_drv);