Merge branch 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[pandora-kernel.git] / drivers / input / joystick / grip_mp.c
index da17eee..8120a9c 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/input.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
+#include <linux/jiffies.h>
 
 #define DRIVER_DESC    "Gravis Grip Multiport driver"
 
@@ -32,23 +33,28 @@ MODULE_LICENSE("GPL");
 #define dbg(format, arg...) do {} while (0)
 #endif
 
+#define GRIP_MAX_PORTS 4
 /*
  * Grip multiport state
  */
 
+struct grip_port {
+       struct input_dev *dev;
+       int mode;
+       int registered;
+
+       /* individual gamepad states */
+       int buttons;
+       int xaxes;
+       int yaxes;
+       int dirty;     /* has the state been updated? */
+};
+
 struct grip_mp {
        struct gameport *gameport;
-       struct input_dev dev[4];
-       int mode[4];
-       int registered[4];
+       struct grip_port *port[GRIP_MAX_PORTS];
        int reads;
        int bads;
-
-       /* individual gamepad states */
-       int buttons[4];
-       int xaxes[4];
-       int yaxes[4];
-       int dirty[4];     /* has the state been updated? */
 };
 
 /*
@@ -85,16 +91,16 @@ struct grip_mp {
 #define GRIP_MODE_GP           2
 #define GRIP_MODE_C64          3
 
-static int grip_btn_gp[]  = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
-static int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
+static const int grip_btn_gp[]  = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
+static const int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
 
-static int grip_abs_gp[]  = { ABS_X, ABS_Y, -1 };
-static int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
+static const int grip_abs_gp[]  = { ABS_X, ABS_Y, -1 };
+static const int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
 
-static int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
-static int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
+static const int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
+static const int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
 
-static char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
+static const char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
 
 static const int init_seq[] = {
        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,9 +110,9 @@ static const int init_seq[] = {
 
 /* Maps multiport directional values to X,Y axis values (each axis encoded in 3 bits) */
 
-static int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
+static const int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
 
-static void register_slot(int i, struct grip_mp *grip);
+static int register_slot(int i, struct grip_mp *grip);
 
 /*
  * Returns whether an odd or even number of bits are on in pkt.
@@ -353,9 +359,10 @@ static int dig_mode_start(struct gameport *gameport, u32 *packet)
 
 static int get_and_decode_packet(struct grip_mp *grip, int flags)
 {
+       struct grip_port *port;
        u32 packet;
        int joytype = 0;
-       int slot = 0;
+       int slot;
 
        /* Get a packet and check for validity */
 
@@ -377,6 +384,8 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
        if ((slot < 0) || (slot > 3))
                return flags;
 
+       port = grip->port[slot];
+
        /*
         * Handle "reset" packets, which occur at startup, and when gamepads
         * are removed or plugged in.  May contain configuration of a new gamepad.
@@ -385,14 +394,14 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
        joytype = (packet >> 16) & 0x1f;
        if (!joytype) {
 
-               if (grip->registered[slot]) {
+               if (port->registered) {
                        printk(KERN_INFO "grip_mp: removing %s, slot %d\n",
-                              grip_name[grip->mode[slot]], slot);
-                       input_unregister_device(grip->dev + slot);
-                       grip->registered[slot] = 0;
+                              grip_name[port->mode], slot);
+                       input_unregister_device(port->dev);
+                       port->registered = 0;
                }
                dbg("Reset: grip multiport slot %d\n", slot);
-               grip->mode[slot] = GRIP_MODE_RESET;
+               port->mode = GRIP_MODE_RESET;
                flags |= IO_SLOT_CHANGE;
                return flags;
        }
@@ -402,19 +411,22 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
        if (joytype == 0x1f) {
 
                int dir = (packet >> 8) & 0xf;          /* eight way directional value */
-               grip->buttons[slot] = (~packet) & 0xff;
-               grip->yaxes[slot] = ((axis_map[dir] >> 2) & 3) - 1;
-               grip->xaxes[slot] = (axis_map[dir] & 3) - 1;
-               grip->dirty[slot] = 1;
+               port->buttons = (~packet) & 0xff;
+               port->yaxes = ((axis_map[dir] >> 2) & 3) - 1;
+               port->xaxes = (axis_map[dir] & 3) - 1;
+               port->dirty = 1;
 
-               if (grip->mode[slot] == GRIP_MODE_RESET)
+               if (port->mode == GRIP_MODE_RESET)
                        flags |= IO_SLOT_CHANGE;
 
-               grip->mode[slot] = GRIP_MODE_GP;
+               port->mode = GRIP_MODE_GP;
 
-               if (!grip->registered[slot]) {
+               if (!port->registered) {
                        dbg("New Grip pad in multiport slot %d.\n", slot);
-                       register_slot(slot, grip);
+                       if (register_slot(slot, grip)) {
+                               port->mode = GRIP_MODE_RESET;
+                               port->dirty = 0;
+                       }
                }
                return flags;
        }
@@ -445,9 +457,9 @@ static int slots_valid(struct grip_mp *grip)
                return 0;
 
        for (slot = 0; slot < 4; slot++) {
-               if (grip->mode[slot] == GRIP_MODE_RESET)
+               if (grip->port[slot]->mode == GRIP_MODE_RESET)
                        invalid = 1;
-               if (grip->mode[slot] != GRIP_MODE_NONE)
+               if (grip->port[slot]->mode != GRIP_MODE_NONE)
                        active = 1;
        }
 
@@ -484,7 +496,7 @@ static int multiport_init(struct grip_mp *grip)
 
        /* Get packets, store multiport state, and check state's validity */
        for (tries = 0; tries < 4096; tries++) {
-               if ( slots_valid(grip) ) {
+               if (slots_valid(grip)) {
                        initialized = 1;
                        break;
                }
@@ -499,24 +511,24 @@ static int multiport_init(struct grip_mp *grip)
 
 static void report_slot(struct grip_mp *grip, int slot)
 {
-       struct input_dev *dev = &(grip->dev[slot]);
-       int i, buttons = grip->buttons[slot];
+       struct grip_port *port = grip->port[slot];
+       int i;
 
        /* Store button states with linux input driver */
 
        for (i = 0; i < 8; i++)
-               input_report_key(dev, grip_btn_gp[i], (buttons >> i) & 1);
+               input_report_key(port->dev, grip_btn_gp[i], (port->buttons >> i) & 1);
 
        /* Store axis states with linux driver */
 
-       input_report_abs(dev, ABS_X, grip->xaxes[slot]);
-       input_report_abs(dev, ABS_Y, grip->yaxes[slot]);
+       input_report_abs(port->dev, ABS_X, port->xaxes);
+       input_report_abs(port->dev, ABS_Y, port->yaxes);
 
        /* Tell the receiver of the events to process them */
 
-       input_sync(dev);
+       input_sync(port->dev);
 
-       grip->dirty[slot] = 0;
+       port->dirty = 0;
 }
 
 /*
@@ -540,7 +552,7 @@ static void grip_poll(struct gameport *gameport)
        }
 
        for (i = 0; i < 4; i++)
-               if (grip->dirty[i])
+               if (grip->port[i]->dirty)
                        report_slot(grip, i);
 }
 
@@ -571,35 +583,49 @@ static void grip_close(struct input_dev *dev)
  * Tell the linux input layer about a newly plugged-in gamepad.
  */
 
-static void register_slot(int slot, struct grip_mp *grip)
+static int register_slot(int slot, struct grip_mp *grip)
 {
+       struct grip_port *port = grip->port[slot];
+       struct input_dev *input_dev;
        int j, t;
+       int err;
+
+       port->dev = input_dev = input_allocate_device();
+       if (!input_dev)
+               return -ENOMEM;
+
+       input_dev->name = grip_name[port->mode];
+       input_dev->id.bustype = BUS_GAMEPORT;
+       input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
+       input_dev->id.product = 0x0100 + port->mode;
+       input_dev->id.version = 0x0100;
+       input_dev->cdev.dev = &grip->gameport->dev;
+       input_dev->private = grip;
 
-       grip->dev[slot].private = grip;
-       grip->dev[slot].open = grip_open;
-       grip->dev[slot].close = grip_close;
-       grip->dev[slot].name = grip_name[grip->mode[slot]];
-       grip->dev[slot].id.bustype = BUS_GAMEPORT;
-       grip->dev[slot].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
-       grip->dev[slot].id.product = 0x0100 + grip->mode[slot];
-       grip->dev[slot].id.version = 0x0100;
-       grip->dev[slot].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+       input_dev->open = grip_open;
+       input_dev->close = grip_close;
 
-       for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++)
-               input_set_abs_params(&grip->dev[slot], t, -1, 1, 0, 0);
+       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
-       for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++)
+       for (j = 0; (t = grip_abs[port->mode][j]) >= 0; j++)
+               input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+
+       for (j = 0; (t = grip_btn[port->mode][j]) >= 0; j++)
                if (t > 0)
-                       set_bit(t, grip->dev[slot].keybit);
+                       set_bit(t, input_dev->keybit);
+
+       err = input_register_device(port->dev);
+       if (err) {
+               input_free_device(port->dev);
+               return err;
+       }
 
-       input_register_device(grip->dev + slot);
-       grip->registered[slot] = 1;
+       port->registered = 1;
 
-       if (grip->dirty[slot])              /* report initial state, if any */
+       if (port->dirty)                    /* report initial state, if any */
                report_slot(grip, slot);
 
-       printk(KERN_INFO "grip_mp: added %s, slot %d\n",
-              grip_name[grip->mode[slot]], slot);
+       return 0;
 }
 
 static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
@@ -626,7 +652,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
                goto fail2;
        }
 
-       if (!grip->mode[0] && !grip->mode[1] && !grip->mode[2] && !grip->mode[3]) {
+       if (!grip->port[0]->mode && !grip->port[1]->mode && !grip->port[2]->mode && !grip->port[3]->mode) {
                /* nothing plugged in */
                err = -ENODEV;
                goto fail2;
@@ -646,8 +672,8 @@ static void grip_disconnect(struct gameport *gameport)
        int i;
 
        for (i = 0; i < 4; i++)
-               if (grip->registered[i])
-                       input_unregister_device(grip->dev + i);
+               if (grip->port[i]->registered)
+                       input_unregister_device(grip->port[i]->dev);
        gameport_close(gameport);
        gameport_set_drvdata(gameport, NULL);
        kfree(grip);