#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/input.h>
+#include <linux/jiffies.h>
+
+#define DRIVER_DESC "Gravis GrIP protocol joystick driver"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Gravis GrIP protocol joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
#define GRIP_MODE_GPP 1
#define GRIP_STROBE_GPP 200 /* 200 us */
#define GRIP_LENGTH_XT 4
#define GRIP_STROBE_XT 64 /* 64 us */
-#define GRIP_MAX_CHUNKS_XT 10
-#define GRIP_MAX_BITS_XT 30
-
-#define GRIP_REFRESH_TIME HZ/50 /* 20 ms */
+#define GRIP_MAX_CHUNKS_XT 10
+#define GRIP_MAX_BITS_XT 30
struct grip {
struct gameport *gameport;
- struct timer_list timer;
- struct input_dev dev[2];
+ struct input_dev *dev[2];
unsigned char mode[2];
- int used;
int reads;
int bads;
char phys[2][32];
static char *grip_name[] = { NULL, "Gravis GamePad Pro", "Gravis Blackhawk Digital",
"Gravis Xterminator Digital", "Gravis Xterminator DualControl" };
-static int *grip_abs[] = { 0, grip_abs_gpp, grip_abs_bd, grip_abs_xt, grip_abs_dc };
-static int *grip_btn[] = { 0, grip_btn_gpp, grip_btn_bd, grip_btn_xt, grip_btn_dc };
+static int *grip_abs[] = { NULL, grip_abs_gpp, grip_abs_bd, grip_abs_xt, grip_abs_dc };
+static int *grip_btn[] = { NULL, grip_btn_gpp, grip_btn_bd, grip_btn_xt, grip_btn_dc };
static char grip_anx[] = { 0, 0, 3, 5, 5 };
static char grip_cen[] = { 0, 0, 2, 2, 4 };
buf = (buf << 1) | (u >> 1);
t = strobe;
i++;
- } else
+ } else
if ((((u ^ v) & (v ^ w)) >> 1) & ~(u | v | w) & 1) {
if (i == 20) {
* grip_timer() repeatedly polls the joysticks and generates events.
*/
-static void grip_timer(unsigned long private)
+static void grip_poll(struct gameport *gameport)
{
- struct grip *grip = (void*) private;
+ struct grip *grip = gameport_get_drvdata(gameport);
unsigned int data[GRIP_LENGTH_XT];
struct input_dev *dev;
int i, j;
for (i = 0; i < 2; i++) {
- dev = grip->dev + i;
+ dev = grip->dev[i];
+ if (!dev)
+ continue;
+
grip->reads++;
switch (grip->mode[i]) {
input_sync(dev);
}
-
- mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
}
static int grip_open(struct input_dev *dev)
{
struct grip *grip = dev->private;
- if (!grip->used++)
- mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
+
+ gameport_start_polling(grip->gameport);
return 0;
}
static void grip_close(struct input_dev *dev)
{
struct grip *grip = dev->private;
- if (!--grip->used)
- del_timer(&grip->timer);
+
+ gameport_stop_polling(grip->gameport);
}
-static void grip_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct grip *grip;
+ struct input_dev *input_dev;
unsigned int data[GRIP_LENGTH_XT];
int i, j, t;
+ int err;
- if (!(grip = kmalloc(sizeof(struct grip), GFP_KERNEL)))
- return;
- memset(grip, 0, sizeof(struct grip));
-
- gameport->private = grip;
+ if (!(grip = kzalloc(sizeof(struct grip), GFP_KERNEL)))
+ return -ENOMEM;
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;
for (i = 0; i < 2; i++) {
}
}
- if (!grip->mode[0] && !grip->mode[1])
+ if (!grip->mode[0] && !grip->mode[1]) {
+ err = -ENODEV;
goto fail2;
+ }
- for (i = 0; i < 2; i++)
- if (grip->mode[i]) {
-
- sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
-
- grip->dev[i].private = grip;
+ gameport_set_poll_handler(gameport, grip_poll);
+ gameport_set_poll_interval(gameport, 20);
- grip->dev[i].open = grip_open;
- grip->dev[i].close = grip_close;
+ for (i = 0; i < 2; i++) {
+ if (!grip->mode[i])
+ continue;
- grip->dev[i].name = grip_name[grip->mode[i]];
- grip->dev[i].phys = grip->phys[i];
- grip->dev[i].id.bustype = BUS_GAMEPORT;
- grip->dev[i].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
- grip->dev[i].id.product = grip->mode[i];
- grip->dev[i].id.version = 0x0100;
+ grip->dev[i] = input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ goto fail3;
+ }
- grip->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ snprintf(grip->phys[i], sizeof(grip->phys[i]),
+ "%s/input%d", gameport->phys, i);
- for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
+ input_dev->name = grip_name[grip->mode[i]];
+ input_dev->phys = grip->phys[i];
+ input_dev->id.bustype = BUS_GAMEPORT;
+ input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
+ input_dev->id.product = grip->mode[i];
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &gameport->dev;
+ input_dev->private = grip;
- set_bit(t, grip->dev[i].absbit);
+ input_dev->open = grip_open;
+ input_dev->close = grip_close;
- if (j < grip_cen[grip->mode[i]]) {
- grip->dev[i].absmin[t] = 14;
- grip->dev[i].absmax[t] = 52;
- grip->dev[i].absfuzz[t] = 1;
- grip->dev[i].absflat[t] = 2;
- continue;
- }
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- if (j < grip_anx[grip->mode[i]]) {
- grip->dev[i].absmin[t] = 3;
- grip->dev[i].absmax[t] = 57;
- grip->dev[i].absfuzz[t] = 1;
- continue;
- }
+ for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
- grip->dev[i].absmin[t] = -1;
- grip->dev[i].absmax[t] = 1;
- }
+ if (j < grip_cen[grip->mode[i]])
+ input_set_abs_params(input_dev, t, 14, 52, 1, 2);
+ else if (j < grip_anx[grip->mode[i]])
+ input_set_abs_params(input_dev, t, 3, 57, 1, 0);
+ else
+ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+ }
- for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
- if (t > 0)
- set_bit(t, grip->dev[i].keybit);
+ for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
+ if (t > 0)
+ set_bit(t, input_dev->keybit);
- input_register_device(grip->dev + i);
+ err = input_register_device(grip->dev[i]);
+ if (err)
+ goto fail4;
+ }
- printk(KERN_INFO "input: %s on %s\n",
- grip_name[grip->mode[i]], gameport->phys);
- }
+ return 0;
- return;
-fail2: gameport_close(gameport);
-fail1: kfree(grip);
+ fail4: input_free_device(grip->dev[i]);
+ fail3: while (--i >= 0)
+ if (grip->dev[i])
+ input_unregister_device(grip->dev[i]);
+ fail2: gameport_close(gameport);
+ fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(grip);
+ return err;
}
static void grip_disconnect(struct gameport *gameport)
{
+ struct grip *grip = gameport_get_drvdata(gameport);
int i;
- struct grip *grip = gameport->private;
for (i = 0; i < 2; i++)
- if (grip->mode[i])
- input_unregister_device(grip->dev + i);
+ if (grip->dev[i])
+ input_unregister_device(grip->dev[i]);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(grip);
}
-static struct gameport_dev grip_dev = {
- .connect = grip_connect,
- .disconnect = grip_disconnect,
+static struct gameport_driver grip_drv = {
+ .driver = {
+ .name = "grip",
+ .owner = THIS_MODULE,
+ },
+ .description = DRIVER_DESC,
+ .connect = grip_connect,
+ .disconnect = grip_disconnect,
};
-int __init grip_init(void)
+static int __init grip_init(void)
{
- gameport_register_device(&grip_dev);
+ gameport_register_driver(&grip_drv);
return 0;
}
-void __exit grip_exit(void)
+static void __exit grip_exit(void)
{
- gameport_unregister_device(&grip_dev);
+ gameport_unregister_driver(&grip_drv);
}
module_init(grip_init);