X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Finput%2Fjoystick%2Fgrip_mp.c;h=8120a9c40773ecc41c8d73837a50bfd287e0c65a;hb=refs%2Fheads%2Fvserver;hp=995caa3e44d7bdc454e33eb4e79117be06352da8;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 995caa3e4..8120a9c40 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c @@ -19,9 +19,12 @@ #include #include #include +#include + +#define DRIVER_DESC "Gravis Grip Multiport driver" MODULE_AUTHOR("Brian Bonnlander"); -MODULE_DESCRIPTION("Gravis Grip Multiport driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); #ifdef GRIP_DEBUG @@ -30,25 +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 timer_list timer; - struct input_dev dev[4]; - int mode[4]; - int registered[4]; - int used; + 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? */ }; /* @@ -79,23 +85,22 @@ struct grip_mp { */ #define GRIP_INIT_DELAY 2000 /* 2 ms */ -#define GRIP_REFRESH_TIME HZ/50 /* 20 ms */ #define GRIP_MODE_NONE 0 #define GRIP_MODE_RESET 1 #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[] = { 0, 0, grip_abs_gp, grip_abs_c64 }; -static int *grip_btn[] = { 0, 0, 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, @@ -105,7 +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 int register_slot(int i, struct grip_mp *grip); /* * Returns whether an odd or even number of bits are on in pkt. @@ -170,7 +177,7 @@ static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *pa *packet = 0; raw_data = gameport_read(gameport); if (raw_data & 1) - return IO_RETRY; + return IO_RETRY; for (i = 0; i < 64; i++) { raw_data = gameport_read(gameport); @@ -352,10 +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; - static void register_slot(int i, struct grip_mp *grip); + 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; } @@ -476,15 +488,15 @@ static int multiport_init(struct grip_mp *grip) } if (dig_mode) - dbg("multiport_init(): digital mode achieved.\n"); + dbg("multiport_init(): digital mode activated.\n"); else { - dbg("multiport_init(): unable to achieve digital mode.\n"); + dbg("multiport_init(): unable to activate digital mode.\n"); return 0; } /* 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,32 +511,33 @@ 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; } /* * Get the multiport state. */ -static void get_and_report_mp_state(struct grip_mp *grip) +static void grip_poll(struct gameport *gameport) { + struct grip_mp *grip = gameport_get_drvdata(gameport); int i, npkts, flags; for (npkts = 0; npkts < 4; npkts++) { @@ -539,7 +552,7 @@ static void get_and_report_mp_state(struct grip_mp *grip) } for (i = 0; i < 4; i++) - if (grip->dirty[i]) + if (grip->port[i]->dirty) report_slot(grip, i); } @@ -550,8 +563,8 @@ static void get_and_report_mp_state(struct grip_mp *grip) static int grip_open(struct input_dev *dev) { struct grip_mp *grip = dev->private; - if (!grip->used++) - mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME); + + gameport_start_polling(grip->gameport); return 0; } @@ -562,111 +575,128 @@ static int grip_open(struct input_dev *dev) static void grip_close(struct input_dev *dev) { struct grip_mp *grip = dev->private; - if (!--grip->used) - del_timer(&grip->timer); + + gameport_start_polling(grip->gameport); } /* * 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; - 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); - - for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++) { - set_bit(t, grip->dev[slot].absbit); - grip->dev[slot].absmin[t] = -1; - grip->dev[slot].absmax[t] = 1; - } + port->dev = input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; - for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++) - if (t > 0) - set_bit(t, grip->dev[slot].keybit); + 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; - input_register_device(grip->dev + slot); - grip->registered[slot] = 1; + input_dev->open = grip_open; + input_dev->close = grip_close; - if (grip->dirty[slot]) /* report initial state, if any */ - report_slot(grip, slot); + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - printk(KERN_INFO "grip_mp: added %s, slot %d\n", - grip_name[grip->mode[slot]], slot); -} + for (j = 0; (t = grip_abs[port->mode][j]) >= 0; j++) + input_set_abs_params(input_dev, t, -1, 1, 0, 0); -/* - * Repeatedly polls the multiport and generates events. - */ + for (j = 0; (t = grip_btn[port->mode][j]) >= 0; j++) + if (t > 0) + set_bit(t, input_dev->keybit); -static void grip_timer(unsigned long private) -{ - struct grip_mp *grip = (void*) private; - get_and_report_mp_state(grip); - mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME); + err = input_register_device(port->dev); + if (err) { + input_free_device(port->dev); + return err; + } + + port->registered = 1; + + if (port->dirty) /* report initial state, if any */ + report_slot(grip, slot); + + return 0; } -static void grip_connect(struct gameport *gameport, struct gameport_dev *dev) +static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) { struct grip_mp *grip; + int err; + + if (!(grip = kzalloc(sizeof(struct grip_mp), GFP_KERNEL))) + return -ENOMEM; - if (!(grip = kmalloc(sizeof(struct grip_mp), GFP_KERNEL))) - return; - memset(grip, 0, sizeof(struct grip_mp)); - gameport->private = grip; grip->gameport = gameport; - init_timer(&grip->timer); - grip->timer.data = (long) grip; - grip->timer.function = grip_timer; - if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) + gameport_set_drvdata(gameport, grip); + + err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW); + if (err) goto fail1; - if (!multiport_init(grip)) + + gameport_set_poll_handler(gameport, grip_poll); + gameport_set_poll_interval(gameport, 20); + + if (!multiport_init(grip)) { + err = -ENODEV; goto fail2; - if (!grip->mode[0] && !grip->mode[1] && /* nothing plugged in */ - !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; - return; + } + + return 0; fail2: gameport_close(gameport); -fail1: kfree(grip); +fail1: gameport_set_drvdata(gameport, NULL); + kfree(grip); + return err; } static void grip_disconnect(struct gameport *gameport) { + struct grip_mp *grip = gameport_get_drvdata(gameport); int i; - struct grip_mp *grip = gameport->private; 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); } -static struct gameport_dev grip_dev = { +static struct gameport_driver grip_drv = { + .driver = { + .name = "grip_mp", + }, + .description = DRIVER_DESC, .connect = grip_connect, .disconnect = grip_disconnect, }; -static int grip_init(void) +static int __init grip_init(void) { - gameport_register_device(&grip_dev); + gameport_register_driver(&grip_drv); return 0; } -static void grip_exit(void) +static void __exit grip_exit(void) { - gameport_unregister_device(&grip_dev); + gameport_unregister_driver(&grip_drv); } module_init(grip_init);