Commit a517e87c authored by Sudip Mukherjee's avatar Sudip Mukherjee Committed by Dmitry Torokhov

Input: gamecon - use parallel port device model

Modify gamecon driver to use the new Parallel Port device model.
Signed-off-by: default avatarSudip Mukherjee <sudip@vectorindia.org>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 379d7cfa
...@@ -53,7 +53,7 @@ struct gc_config { ...@@ -53,7 +53,7 @@ struct gc_config {
unsigned int nargs; unsigned int nargs;
}; };
static struct gc_config gc_cfg[GC_MAX_PORTS] __initdata; static struct gc_config gc_cfg[GC_MAX_PORTS];
module_param_array_named(map, gc_cfg[0].args, int, &gc_cfg[0].nargs, 0); module_param_array_named(map, gc_cfg[0].args, int, &gc_cfg[0].nargs, 0);
MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)"); MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
...@@ -92,6 +92,7 @@ struct gc { ...@@ -92,6 +92,7 @@ struct gc {
struct timer_list timer; struct timer_list timer;
int pad_count[GC_MAX]; int pad_count[GC_MAX];
int used; int used;
int parportno;
struct mutex mutex; struct mutex mutex;
}; };
...@@ -304,7 +305,7 @@ static int gc_n64_play_effect(struct input_dev *dev, void *data, ...@@ -304,7 +305,7 @@ static int gc_n64_play_effect(struct input_dev *dev, void *data,
return 0; return 0;
} }
static int __init gc_n64_init_ff(struct input_dev *dev, int i) static int gc_n64_init_ff(struct input_dev *dev, int i)
{ {
struct gc_subdev *sdev; struct gc_subdev *sdev;
int err; int err;
...@@ -811,7 +812,7 @@ static void gc_close(struct input_dev *dev) ...@@ -811,7 +812,7 @@ static void gc_close(struct input_dev *dev)
mutex_unlock(&gc->mutex); mutex_unlock(&gc->mutex);
} }
static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) static int gc_setup_pad(struct gc *gc, int idx, int pad_type)
{ {
struct gc_pad *pad = &gc->pads[idx]; struct gc_pad *pad = &gc->pads[idx];
struct input_dev *input_dev; struct input_dev *input_dev;
...@@ -926,46 +927,54 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) ...@@ -926,46 +927,54 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
return err; return err;
} }
static struct gc __init *gc_probe(int parport, int *pads, int n_pads) static void gc_attach(struct parport *pp)
{ {
struct gc *gc; struct gc *gc;
struct parport *pp;
struct pardevice *pd; struct pardevice *pd;
int i; int i;
int count = 0; int count = 0;
int err; int *pads, n_pads;
struct pardev_cb gc_parport_cb;
for (i = 0; i < GC_MAX_PORTS; i++) {
if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0)
continue;
if (gc_cfg[i].args[0] == pp->number)
break;
}
pp = parport_find_number(parport); if (i == GC_MAX_PORTS) {
if (!pp) { pr_debug("Not using parport%d.\n", pp->number);
pr_err("no such parport %d\n", parport); return;
err = -EINVAL;
goto err_out;
} }
pads = gc_cfg[i].args + 1;
n_pads = gc_cfg[i].nargs - 1;
gc_parport_cb.flags = PARPORT_FLAG_EXCL;
pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb, i);
if (!pd) { if (!pd) {
pr_err("parport busy already - lp.o loaded?\n"); pr_err("parport busy already - lp.o loaded?\n");
err = -EBUSY; return;
goto err_put_pp;
} }
gc = kzalloc(sizeof(struct gc), GFP_KERNEL); gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
if (!gc) { if (!gc) {
pr_err("Not enough memory\n"); pr_err("Not enough memory\n");
err = -ENOMEM;
goto err_unreg_pardev; goto err_unreg_pardev;
} }
mutex_init(&gc->mutex); mutex_init(&gc->mutex);
gc->pd = pd; gc->pd = pd;
gc->parportno = pp->number;
setup_timer(&gc->timer, gc_timer, (long) gc); setup_timer(&gc->timer, gc_timer, (long) gc);
for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) { for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) {
if (!pads[i]) if (!pads[i])
continue; continue;
err = gc_setup_pad(gc, i, pads[i]); if (gc_setup_pad(gc, i, pads[i]))
if (err)
goto err_unreg_devs; goto err_unreg_devs;
count++; count++;
...@@ -973,12 +982,11 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) ...@@ -973,12 +982,11 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
if (count == 0) { if (count == 0) {
pr_err("No valid devices specified\n"); pr_err("No valid devices specified\n");
err = -EINVAL;
goto err_free_gc; goto err_free_gc;
} }
parport_put_port(pp); gc_base[i] = gc;
return gc; return;
err_unreg_devs: err_unreg_devs:
while (--i >= 0) while (--i >= 0)
...@@ -988,15 +996,23 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) ...@@ -988,15 +996,23 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
kfree(gc); kfree(gc);
err_unreg_pardev: err_unreg_pardev:
parport_unregister_device(pd); parport_unregister_device(pd);
err_put_pp:
parport_put_port(pp);
err_out:
return ERR_PTR(err);
} }
static void gc_remove(struct gc *gc) static void gc_detach(struct parport *port)
{ {
int i; int i;
struct gc *gc;
for (i = 0; i < GC_MAX_PORTS; i++) {
if (gc_base[i] && gc_base[i]->parportno == port->number)
break;
}
if (i == GC_MAX_PORTS)
return;
gc = gc_base[i];
gc_base[i] = NULL;
for (i = 0; i < GC_MAX_DEVICES; i++) for (i = 0; i < GC_MAX_DEVICES; i++)
if (gc->pads[i].dev) if (gc->pads[i].dev)
...@@ -1005,11 +1021,17 @@ static void gc_remove(struct gc *gc) ...@@ -1005,11 +1021,17 @@ static void gc_remove(struct gc *gc)
kfree(gc); kfree(gc);
} }
static struct parport_driver gc_parport_driver = {
.name = "gamecon",
.match_port = gc_attach,
.detach = gc_detach,
.devmodel = true,
};
static int __init gc_init(void) static int __init gc_init(void)
{ {
int i; int i;
int have_dev = 0; int have_dev = 0;
int err = 0;
for (i = 0; i < GC_MAX_PORTS; i++) { for (i = 0; i < GC_MAX_PORTS; i++) {
if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0) if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0)
...@@ -1017,37 +1039,21 @@ static int __init gc_init(void) ...@@ -1017,37 +1039,21 @@ static int __init gc_init(void)
if (gc_cfg[i].nargs < 2) { if (gc_cfg[i].nargs < 2) {
pr_err("at least one device must be specified\n"); pr_err("at least one device must be specified\n");
err = -EINVAL; return -EINVAL;
break;
}
gc_base[i] = gc_probe(gc_cfg[i].args[0],
gc_cfg[i].args + 1, gc_cfg[i].nargs - 1);
if (IS_ERR(gc_base[i])) {
err = PTR_ERR(gc_base[i]);
break;
} }
have_dev = 1; have_dev = 1;
} }
if (err) { if (!have_dev)
while (--i >= 0) return -ENODEV;
if (gc_base[i])
gc_remove(gc_base[i]);
return err;
}
return have_dev ? 0 : -ENODEV; return parport_register_driver(&gc_parport_driver);
} }
static void __exit gc_exit(void) static void __exit gc_exit(void)
{ {
int i; parport_unregister_driver(&gc_parport_driver);
for (i = 0; i < GC_MAX_PORTS; i++)
if (gc_base[i])
gc_remove(gc_base[i]);
} }
module_init(gc_init); module_init(gc_init);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment