[PATCH] drivers/input/joystick: convert to dynamic input_dev allocation

Input: convert drivers/input/joystick to dynamic input_dev allocation

This is required for input_dev sysfs integration

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Dmitry Torokhov
2005-09-15 02:01:52 -05:00
committed by Greg Kroah-Hartman
parent 0259567ad6
commit 17dd3f0f7a
25 changed files with 1486 additions and 1256 deletions

View File

@@ -41,20 +41,22 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
MODULE_LICENSE("GPL");
static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 };
static int gc_nargs __initdata = 0;
module_param_array_named(map, gc, int, &gc_nargs, 0);
MODULE_PARM_DESC(map, "Describers first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
#define GC_MAX_PORTS 3
#define GC_MAX_DEVICES 5
static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 };
static int gc_nargs_2 __initdata = 0;
module_param_array_named(map2, gc_2, int, &gc_nargs_2, 0);
MODULE_PARM_DESC(map2, "Describers second set of devices");
struct gc_config {
int args[GC_MAX_DEVICES + 1];
int nargs;
};
static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 };
static int gc_nargs_3 __initdata = 0;
module_param_array_named(map3, gc_3, int, &gc_nargs_3, 0);
MODULE_PARM_DESC(map3, "Describers third set of devices");
static struct gc_config gc[GC_MAX_PORTS] __initdata;
module_param_array_named(map, gc[0].args, int, &gc[0].nargs, 0);
MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
module_param_array_named(map2, gc[1].args, int, &gc[1].nargs, 0);
MODULE_PARM_DESC(map2, "Describes second set of devices");
module_param_array_named(map3, gc[2].args, int, &gc[2].nargs, 0);
MODULE_PARM_DESC(map3, "Describes third set of devices");
__obsolete_setup("gc=");
__obsolete_setup("gc_2=");
@@ -77,12 +79,12 @@ __obsolete_setup("gc_3=");
struct gc {
struct pardevice *pd;
struct input_dev dev[5];
struct input_dev *dev[GC_MAX_DEVICES];
struct timer_list timer;
unsigned char pads[GC_MAX + 1];
int used;
struct semaphore sem;
char phys[5][32];
char phys[GC_MAX_DEVICES][32];
};
static struct gc *gc_base[3];
@@ -330,7 +332,6 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES
static void gc_timer(unsigned long private)
{
struct gc *gc = (void *) private;
struct input_dev *dev = gc->dev;
unsigned char data[GC_MAX_LENGTH];
unsigned char data_psx[5][GC_PSX_BYTES];
int i, j, s;
@@ -357,16 +358,16 @@ static void gc_timer(unsigned long private)
if (data[31 - j] & s) axes[1] |= 1 << j;
}
input_report_abs(dev + i, ABS_X, axes[0]);
input_report_abs(dev + i, ABS_Y, -axes[1]);
input_report_abs(gc->dev[i], ABS_X, axes[0]);
input_report_abs(gc->dev[i], ABS_Y, -axes[1]);
input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
input_report_abs(gc->dev[i], ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
input_report_abs(gc->dev[i], ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
for (j = 0; j < 10; j++)
input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
input_report_key(gc->dev[i], gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
input_sync(dev + i);
input_sync(gc->dev[i]);
}
}
}
@@ -384,19 +385,19 @@ static void gc_timer(unsigned long private)
s = gc_status_bit[i];
if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
input_report_abs(dev + i, ABS_X, !(s & data[6]) - !(s & data[7]));
input_report_abs(dev + i, ABS_Y, !(s & data[4]) - !(s & data[5]));
input_report_abs(gc->dev[i], ABS_X, !(s & data[6]) - !(s & data[7]));
input_report_abs(gc->dev[i], ABS_Y, !(s & data[4]) - !(s & data[5]));
}
if (s & gc->pads[GC_NES])
for (j = 0; j < 4; j++)
input_report_key(dev + i, gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
if (s & gc->pads[GC_SNES])
for (j = 0; j < 8; j++)
input_report_key(dev + i, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
input_sync(dev + i);
input_sync(gc->dev[i]);
}
}
@@ -413,15 +414,15 @@ static void gc_timer(unsigned long private)
s = gc_status_bit[i];
if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
input_report_abs(dev + i, ABS_X, !(s & data[2]) - !(s & data[3]));
input_report_abs(dev + i, ABS_Y, !(s & data[0]) - !(s & data[1]));
input_report_key(dev + i, BTN_TRIGGER, s & data[4]);
input_report_abs(gc->dev[i], ABS_X, !(s & data[2]) - !(s & data[3]));
input_report_abs(gc->dev[i], ABS_Y, !(s & data[0]) - !(s & data[1]));
input_report_key(gc->dev[i], BTN_TRIGGER, s & data[4]);
}
if (s & gc->pads[GC_MULTI2])
input_report_key(dev + i, BTN_THUMB, s & data[5]);
input_report_key(gc->dev[i], BTN_THUMB, s & data[5]);
input_sync(dev + i);
input_sync(gc->dev[i]);
}
}
@@ -438,44 +439,44 @@ static void gc_timer(unsigned long private)
case GC_PSX_RUMBLE:
input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04);
input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02);
input_report_key(gc->dev[i], BTN_THUMBL, ~data_psx[i][0] & 0x04);
input_report_key(gc->dev[i], BTN_THUMBR, ~data_psx[i][0] & 0x02);
case GC_PSX_NEGCON:
case GC_PSX_ANALOG:
if(gc->pads[GC_DDR] & gc_status_bit[i]) {
if (gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++)
input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
} else {
for (j = 0; j < 4; j++)
input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]);
input_report_abs(gc->dev[i], gc_psx_abs[j+2], data_psx[i][j + 2]);
input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
}
for (j = 0; j < 8; j++)
input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08);
input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
input_sync(dev + i);
input_sync(gc->dev[i]);
break;
case GC_PSX_NORMAL:
if(gc->pads[GC_DDR] & gc_status_bit[i]) {
if (gc->pads[GC_DDR] & gc_status_bit[i]) {
for(j = 0; j < 4; j++)
input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
} else {
input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
/* for some reason if the extra axes are left unset they drift */
/* for (j = 0; j < 4; j++)
input_report_abs(dev + i, gc_psx_abs[j+2], 128);
input_report_abs(gc->dev[i], gc_psx_abs[j+2], 128);
* This needs to be debugged properly,
* maybe fuzz processing needs to be done in input_sync()
* --vojtech
@@ -483,12 +484,12 @@ static void gc_timer(unsigned long private)
}
for (j = 0; j < 8; j++)
input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08);
input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
input_sync(dev + i);
input_sync(gc->dev[i]);
break;
@@ -533,177 +534,212 @@ static void gc_close(struct input_dev *dev)
up(&gc->sem);
}
static struct gc __init *gc_probe(int *config, int nargs)
static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
{
struct input_dev *input_dev;
int i;
if (!pad_type)
return 0;
if (pad_type < 1 || pad_type > GC_MAX) {
printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type);
return -EINVAL;
}
gc->dev[idx] = input_dev = input_allocate_device();
if (!input_dev) {
printk(KERN_ERR "gamecon.c: Not enough memory for input device\n");
return -ENOMEM;
}
input_dev->name = gc_names[pad_type];
input_dev->phys = gc->phys[idx];
input_dev->id.bustype = BUS_PARPORT;
input_dev->id.vendor = 0x0001;
input_dev->id.product = pad_type;
input_dev->id.version = 0x0100;
input_dev->private = gc;
input_dev->open = gc_open;
input_dev->close = gc_close;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (i = 0; i < 2; i++)
input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
gc->pads[0] |= gc_status_bit[idx];
gc->pads[pad_type] |= gc_status_bit[idx];
switch (pad_type) {
case GC_N64:
for (i = 0; i < 10; i++)
set_bit(gc_n64_btn[i], input_dev->keybit);
for (i = 0; i < 2; i++) {
input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2);
input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);
}
break;
case GC_SNES:
for (i = 4; i < 8; i++)
set_bit(gc_snes_btn[i], input_dev->keybit);
case GC_NES:
for (i = 0; i < 4; i++)
set_bit(gc_snes_btn[i], input_dev->keybit);
break;
case GC_MULTI2:
set_bit(BTN_THUMB, input_dev->keybit);
case GC_MULTI:
set_bit(BTN_TRIGGER, input_dev->keybit);
break;
case GC_PSX:
for (i = 0; i < 6; i++)
input_set_abs_params(input_dev, gc_psx_abs[i], 4, 252, 0, 2);
for (i = 0; i < 12; i++)
set_bit(gc_psx_btn[i], input_dev->keybit);
break;
case GC_DDR:
for (i = 0; i < 4; i++)
set_bit(gc_psx_ddr_btn[i], input_dev->keybit);
for (i = 0; i < 12; i++)
set_bit(gc_psx_btn[i], input_dev->keybit);
break;
}
return 0;
}
static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
{
struct gc *gc;
struct parport *pp;
int i, j;
if (config[0] < 0)
return NULL;
if (nargs < 2) {
printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
return NULL;
}
pp = parport_find_number(config[0]);
struct pardevice *pd;
int i;
int err;
pp = parport_find_number(parport);
if (!pp) {
printk(KERN_ERR "gamecon.c: no such parport\n");
return NULL;
err = -EINVAL;
goto err_out;
}
if (!(gc = kzalloc(sizeof(struct gc), GFP_KERNEL))) {
parport_put_port(pp);
return NULL;
pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
if (!pd) {
printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
err = -EBUSY;
goto err_put_pp;
}
gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
if (!gc) {
printk(KERN_ERR "gamecon.c: Not enough memory\n");
err = -ENOMEM;
goto err_unreg_pardev;
}
init_MUTEX(&gc->sem);
gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
parport_put_port(pp);
if (!gc->pd) {
printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
kfree(gc);
return NULL;
}
parport_claim(gc->pd);
gc->pd = pd;
init_timer(&gc->timer);
gc->timer.data = (long) gc;
gc->timer.function = gc_timer;
for (i = 0; i < nargs - 1; i++) {
if (!config[i + 1])
for (i = 0; i < n_pads; i++) {
if (!pads[i])
continue;
if (config[i + 1] < 1 || config[i + 1] > GC_MAX) {
printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", config[i + 1]);
continue;
}
gc->dev[i].private = gc;
gc->dev[i].open = gc_open;
gc->dev[i].close = gc_close;
gc->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
for (j = 0; j < 2; j++) {
set_bit(ABS_X + j, gc->dev[i].absbit);
gc->dev[i].absmin[ABS_X + j] = -1;
gc->dev[i].absmax[ABS_X + j] = 1;
}
gc->pads[0] |= gc_status_bit[i];
gc->pads[config[i + 1]] |= gc_status_bit[i];
switch(config[i + 1]) {
case GC_N64:
for (j = 0; j < 10; j++)
set_bit(gc_n64_btn[j], gc->dev[i].keybit);
for (j = 0; j < 2; j++) {
set_bit(ABS_X + j, gc->dev[i].absbit);
gc->dev[i].absmin[ABS_X + j] = -127;
gc->dev[i].absmax[ABS_X + j] = 126;
gc->dev[i].absflat[ABS_X + j] = 2;
set_bit(ABS_HAT0X + j, gc->dev[i].absbit);
gc->dev[i].absmin[ABS_HAT0X + j] = -1;
gc->dev[i].absmax[ABS_HAT0X + j] = 1;
}
break;
case GC_SNES:
for (j = 4; j < 8; j++)
set_bit(gc_snes_btn[j], gc->dev[i].keybit);
case GC_NES:
for (j = 0; j < 4; j++)
set_bit(gc_snes_btn[j], gc->dev[i].keybit);
break;
case GC_MULTI2:
set_bit(BTN_THUMB, gc->dev[i].keybit);
case GC_MULTI:
set_bit(BTN_TRIGGER, gc->dev[i].keybit);
break;
case GC_PSX:
case GC_DDR:
if(config[i + 1] == GC_DDR) {
for (j = 0; j < 4; j++)
set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit);
} else {
for (j = 0; j < 6; j++) {
set_bit(gc_psx_abs[j], gc->dev[i].absbit);
gc->dev[i].absmin[gc_psx_abs[j]] = 4;
gc->dev[i].absmax[gc_psx_abs[j]] = 252;
gc->dev[i].absflat[gc_psx_abs[j]] = 2;
}
}
for (j = 0; j < 12; j++)
set_bit(gc_psx_btn[j], gc->dev[i].keybit);
break;
}
sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
err = gc_setup_pad(gc, i, pads[i]);
if (err)
goto err_free_devs;
gc->dev[i].name = gc_names[config[i + 1]];
gc->dev[i].phys = gc->phys[i];
gc->dev[i].id.bustype = BUS_PARPORT;
gc->dev[i].id.vendor = 0x0001;
gc->dev[i].id.product = config[i + 1];
gc->dev[i].id.version = 0x0100;
input_register_device(gc->dev[i]);
}
parport_release(gc->pd);
if (!gc->pads[0]) {
parport_unregister_device(gc->pd);
kfree(gc);
return NULL;
printk(KERN_ERR "gamecon.c: No valid devices specified\n");
err = -EINVAL;
goto err_free_gc;
}
for (i = 0; i < 5; i++)
if (gc->pads[0] & gc_status_bit[i]) {
input_register_device(gc->dev + i);
printk(KERN_INFO "input: %s on %s\n", gc->dev[i].name, gc->pd->port->name);
}
parport_put_port(pp);
return gc;
err_free_devs:
while (--i >= 0)
input_unregister_device(gc->dev[i]);
err_free_gc:
kfree(gc);
err_unreg_pardev:
parport_unregister_device(pd);
err_put_pp:
parport_put_port(pp);
err_out:
return ERR_PTR(err);
}
static void __exit gc_remove(struct gc *gc)
{
int i;
for (i = 0; i < GC_MAX_DEVICES; i++)
if (gc->dev[i])
input_unregister_device(gc->dev[i]);
parport_unregister_device(gc->pd);
kfree(gc);
}
static int __init gc_init(void)
{
gc_base[0] = gc_probe(gc, gc_nargs);
gc_base[1] = gc_probe(gc_2, gc_nargs_2);
gc_base[2] = gc_probe(gc_3, gc_nargs_3);
int i;
int have_dev = 0;
int err = 0;
if (gc_base[0] || gc_base[1] || gc_base[2])
return 0;
for (i = 0; i < GC_MAX_PORTS; i++) {
if (gc[i].nargs == 0 || gc[i].args[0] < 0)
continue;
return -ENODEV;
if (gc[i].nargs < 2) {
printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
err = -EINVAL;
break;
}
gc_base[i] = gc_probe(gc[i].args[0], gc[i].args + 1, gc[i].nargs - 1);
if (IS_ERR(gc_base[i])) {
err = PTR_ERR(gc_base[i]);
break;
}
have_dev = 1;
}
if (err) {
while (--i >= 0)
gc_remove(gc_base[i]);
return err;
}
return have_dev ? 0 : -ENODEV;
}
static void __exit gc_exit(void)
{
int i, j;
int i;
for (i = 0; i < 3; i++)
if (gc_base[i]) {
for (j = 0; j < 5; j++)
if (gc_base[i]->pads[0] & gc_status_bit[j])
input_unregister_device(gc_base[i]->dev + j);
parport_unregister_device(gc_base[i]->pd);
}
for (i = 0; i < GC_MAX_PORTS; i++)
if (gc_base[i])
gc_remove(gc_base[i]);
}
module_init(gc_init);