diff options
author | 2016-04-11 10:41:07 +0300 | |
---|---|---|
committer | 2016-04-13 08:17:18 +0300 | |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/input/joystick | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/input/joystick')
-rw-r--r-- | kernel/drivers/input/joystick/Kconfig | 1 | ||||
-rw-r--r-- | kernel/drivers/input/joystick/analog.c | 4 | ||||
-rw-r--r-- | kernel/drivers/input/joystick/db9.c | 114 | ||||
-rw-r--r-- | kernel/drivers/input/joystick/gamecon.c | 104 | ||||
-rw-r--r-- | kernel/drivers/input/joystick/turbografx.c | 107 | ||||
-rw-r--r-- | kernel/drivers/input/joystick/walkera0701.c | 65 | ||||
-rw-r--r-- | kernel/drivers/input/joystick/xpad.c | 596 | ||||
-rw-r--r-- | kernel/drivers/input/joystick/zhenhua.c | 13 |
8 files changed, 550 insertions, 454 deletions
diff --git a/kernel/drivers/input/joystick/Kconfig b/kernel/drivers/input/joystick/Kconfig index 56eb471b5..4215b5382 100644 --- a/kernel/drivers/input/joystick/Kconfig +++ b/kernel/drivers/input/joystick/Kconfig @@ -196,6 +196,7 @@ config JOYSTICK_TWIDJOY config JOYSTICK_ZHENHUA tristate "5-byte Zhenhua RC transmitter" select SERIO + select BITREVERSE help Say Y here if you have a Zhen Hua PPM-4CH transmitter which is supplied with a ready to fly micro electric indoor helicopters diff --git a/kernel/drivers/input/joystick/analog.c b/kernel/drivers/input/joystick/analog.c index 4284080e4..6f8b084e1 100644 --- a/kernel/drivers/input/joystick/analog.c +++ b/kernel/drivers/input/joystick/analog.c @@ -143,7 +143,7 @@ struct analog_port { #include <linux/i8253.h> -#define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0) +#define GET_TIME(x) do { if (cpu_has_tsc) x = (unsigned int)rdtsc(); else x = get_time_pit(); } while (0) #define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? PIT_TICK_RATE / HZ : 0))) #define TIME_NAME (cpu_has_tsc?"TSC":"PIT") static unsigned int get_time_pit(void) @@ -160,7 +160,7 @@ static unsigned int get_time_pit(void) return count; } #elif defined(__x86_64__) -#define GET_TIME(x) rdtscl(x) +#define GET_TIME(x) do { x = (unsigned int)rdtsc(); } while (0) #define DELTA(x,y) ((y)-(x)) #define TIME_NAME "TSC" #elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_TILE) diff --git a/kernel/drivers/input/joystick/db9.c b/kernel/drivers/input/joystick/db9.c index 8e7de5c77..da326090c 100644 --- a/kernel/drivers/input/joystick/db9.c +++ b/kernel/drivers/input/joystick/db9.c @@ -48,7 +48,7 @@ struct db9_config { }; #define DB9_MAX_PORTS 3 -static struct db9_config db9_cfg[DB9_MAX_PORTS] __initdata; +static struct db9_config db9_cfg[DB9_MAX_PORTS]; module_param_array_named(dev, db9_cfg[0].args, int, &db9_cfg[0].nargs, 0); MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)"); @@ -106,6 +106,7 @@ struct db9 { struct pardevice *pd; int mode; int used; + int parportno; struct mutex mutex; char phys[DB9_MAX_DEVICES][32]; }; @@ -553,54 +554,61 @@ static void db9_close(struct input_dev *dev) mutex_unlock(&db9->mutex); } -static struct db9 __init *db9_probe(int parport, int mode) +static void db9_attach(struct parport *pp) { struct db9 *db9; const struct db9_mode_data *db9_mode; - struct parport *pp; struct pardevice *pd; struct input_dev *input_dev; - int i, j; - int err; + int i, j, port_idx; + int mode; + struct pardev_cb db9_parport_cb; + + for (port_idx = 0; port_idx < DB9_MAX_PORTS; port_idx++) { + if (db9_cfg[port_idx].nargs == 0 || + db9_cfg[port_idx].args[DB9_ARG_PARPORT] < 0) + continue; + + if (db9_cfg[port_idx].args[DB9_ARG_PARPORT] == pp->number) + break; + } + + if (port_idx == DB9_MAX_PORTS) { + pr_debug("Not using parport%d.\n", pp->number); + return; + } + + mode = db9_cfg[port_idx].args[DB9_ARG_MODE]; if (mode < 1 || mode >= DB9_MAX_PAD || !db9_modes[mode].n_buttons) { printk(KERN_ERR "db9.c: Bad device type %d\n", mode); - err = -EINVAL; - goto err_out; + return; } db9_mode = &db9_modes[mode]; - pp = parport_find_number(parport); - if (!pp) { - printk(KERN_ERR "db9.c: no such parport\n"); - err = -ENODEV; - goto err_out; - } - if (db9_mode->bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) { printk(KERN_ERR "db9.c: specified parport is not bidirectional\n"); - err = -EINVAL; - goto err_put_pp; + return; } - pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); + memset(&db9_parport_cb, 0, sizeof(db9_parport_cb)); + db9_parport_cb.flags = PARPORT_FLAG_EXCL; + + pd = parport_register_dev_model(pp, "db9", &db9_parport_cb, port_idx); if (!pd) { printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n"); - err = -EBUSY; - goto err_put_pp; + return; } db9 = kzalloc(sizeof(struct db9), GFP_KERNEL); - if (!db9) { - printk(KERN_ERR "db9.c: Not enough memory\n"); - err = -ENOMEM; + if (!db9) goto err_unreg_pardev; - } mutex_init(&db9->mutex); db9->pd = pd; db9->mode = mode; + db9->parportno = pp->number; init_timer(&db9->timer); db9->timer.data = (long) db9; db9->timer.function = db9_timer; @@ -610,7 +618,6 @@ static struct db9 __init *db9_probe(int parport, int mode) db9->dev[i] = input_dev = input_allocate_device(); if (!input_dev) { printk(KERN_ERR "db9.c: Not enough memory for input device\n"); - err = -ENOMEM; goto err_unreg_devs; } @@ -639,13 +646,12 @@ static struct db9 __init *db9_probe(int parport, int mode) input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0); } - err = input_register_device(input_dev); - if (err) + if (input_register_device(input_dev)) goto err_free_dev; } - parport_put_port(pp); - return db9; + db9_base[port_idx] = db9; + return; err_free_dev: input_free_device(db9->dev[i]); @@ -655,15 +661,23 @@ static struct db9 __init *db9_probe(int parport, int mode) kfree(db9); err_unreg_pardev: parport_unregister_device(pd); - err_put_pp: - parport_put_port(pp); - err_out: - return ERR_PTR(err); } -static void db9_remove(struct db9 *db9) +static void db9_detach(struct parport *port) { int i; + struct db9 *db9; + + for (i = 0; i < DB9_MAX_PORTS; i++) { + if (db9_base[i] && db9_base[i]->parportno == port->number) + break; + } + + if (i == DB9_MAX_PORTS) + return; + + db9 = db9_base[i]; + db9_base[i] = NULL; for (i = 0; i < min(db9_modes[db9->mode].n_pads, DB9_MAX_DEVICES); i++) input_unregister_device(db9->dev[i]); @@ -671,11 +685,17 @@ static void db9_remove(struct db9 *db9) kfree(db9); } +static struct parport_driver db9_parport_driver = { + .name = "db9", + .match_port = db9_attach, + .detach = db9_detach, + .devmodel = true, +}; + static int __init db9_init(void) { int i; int have_dev = 0; - int err = 0; for (i = 0; i < DB9_MAX_PORTS; i++) { if (db9_cfg[i].nargs == 0 || db9_cfg[i].args[DB9_ARG_PARPORT] < 0) @@ -683,37 +703,21 @@ static int __init db9_init(void) if (db9_cfg[i].nargs < 2) { printk(KERN_ERR "db9.c: Device type must be specified.\n"); - err = -EINVAL; - break; - } - - db9_base[i] = db9_probe(db9_cfg[i].args[DB9_ARG_PARPORT], - db9_cfg[i].args[DB9_ARG_MODE]); - if (IS_ERR(db9_base[i])) { - err = PTR_ERR(db9_base[i]); - break; + return -EINVAL; } have_dev = 1; } - if (err) { - while (--i >= 0) - if (db9_base[i]) - db9_remove(db9_base[i]); - return err; - } + if (!have_dev) + return -ENODEV; - return have_dev ? 0 : -ENODEV; + return parport_register_driver(&db9_parport_driver); } static void __exit db9_exit(void) { - int i; - - for (i = 0; i < DB9_MAX_PORTS; i++) - if (db9_base[i]) - db9_remove(db9_base[i]); + parport_unregister_driver(&db9_parport_driver); } module_init(db9_init); diff --git a/kernel/drivers/input/joystick/gamecon.c b/kernel/drivers/input/joystick/gamecon.c index e68e49786..eae14d512 100644 --- a/kernel/drivers/input/joystick/gamecon.c +++ b/kernel/drivers/input/joystick/gamecon.c @@ -53,7 +53,7 @@ struct gc_config { 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_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)"); @@ -92,6 +92,7 @@ struct gc { struct timer_list timer; int pad_count[GC_MAX]; int used; + int parportno; struct mutex mutex; }; @@ -304,7 +305,7 @@ static int gc_n64_play_effect(struct input_dev *dev, void *data, 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; int err; @@ -811,7 +812,7 @@ static void gc_close(struct input_dev *dev) 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 input_dev *input_dev; @@ -926,46 +927,56 @@ err_free_dev: 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 parport *pp; struct pardevice *pd; - int i; + int i, port_idx; int count = 0; - int err; + int *pads, n_pads; + struct pardev_cb gc_parport_cb; + + for (port_idx = 0; port_idx < GC_MAX_PORTS; port_idx++) { + if (gc_cfg[port_idx].nargs == 0 || gc_cfg[port_idx].args[0] < 0) + continue; + + if (gc_cfg[port_idx].args[0] == pp->number) + break; + } - pp = parport_find_number(parport); - if (!pp) { - pr_err("no such parport %d\n", parport); - err = -EINVAL; - goto err_out; + if (port_idx == GC_MAX_PORTS) { + pr_debug("Not using parport%d.\n", pp->number); + return; } + pads = gc_cfg[port_idx].args + 1; + n_pads = gc_cfg[port_idx].nargs - 1; - pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); + memset(&gc_parport_cb, 0, sizeof(gc_parport_cb)); + gc_parport_cb.flags = PARPORT_FLAG_EXCL; + + pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb, + port_idx); if (!pd) { pr_err("parport busy already - lp.o loaded?\n"); - err = -EBUSY; - goto err_put_pp; + return; } gc = kzalloc(sizeof(struct gc), GFP_KERNEL); if (!gc) { pr_err("Not enough memory\n"); - err = -ENOMEM; goto err_unreg_pardev; } mutex_init(&gc->mutex); gc->pd = pd; + gc->parportno = pp->number; setup_timer(&gc->timer, gc_timer, (long) gc); for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) { if (!pads[i]) continue; - err = gc_setup_pad(gc, i, pads[i]); - if (err) + if (gc_setup_pad(gc, i, pads[i])) goto err_unreg_devs; count++; @@ -973,12 +984,11 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) if (count == 0) { pr_err("No valid devices specified\n"); - err = -EINVAL; goto err_free_gc; } - parport_put_port(pp); - return gc; + gc_base[port_idx] = gc; + return; err_unreg_devs: while (--i >= 0) @@ -988,15 +998,23 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) kfree(gc); err_unreg_pardev: 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; + 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++) if (gc->pads[i].dev) @@ -1005,11 +1023,17 @@ static void gc_remove(struct gc *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) { int i; int have_dev = 0; - int err = 0; for (i = 0; i < GC_MAX_PORTS; i++) { if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0) @@ -1017,37 +1041,21 @@ static int __init gc_init(void) if (gc_cfg[i].nargs < 2) { pr_err("at least one device must be specified\n"); - err = -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; + return -EINVAL; } have_dev = 1; } - if (err) { - while (--i >= 0) - if (gc_base[i]) - gc_remove(gc_base[i]); - return err; - } + if (!have_dev) + return -ENODEV; - return have_dev ? 0 : -ENODEV; + return parport_register_driver(&gc_parport_driver); } static void __exit gc_exit(void) { - int i; - - for (i = 0; i < GC_MAX_PORTS; i++) - if (gc_base[i]) - gc_remove(gc_base[i]); + parport_unregister_driver(&gc_parport_driver); } module_init(gc_init); diff --git a/kernel/drivers/input/joystick/turbografx.c b/kernel/drivers/input/joystick/turbografx.c index 27b6a3ce1..77f575dd0 100644 --- a/kernel/drivers/input/joystick/turbografx.c +++ b/kernel/drivers/input/joystick/turbografx.c @@ -49,7 +49,7 @@ struct tgfx_config { unsigned int nargs; }; -static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS] __initdata; +static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS]; module_param_array_named(map, tgfx_cfg[0].args, int, &tgfx_cfg[0].nargs, 0); MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>"); @@ -81,6 +81,7 @@ static struct tgfx { char phys[TGFX_MAX_DEVICES][32]; int sticks; int used; + int parportno; struct mutex sem; } *tgfx_base[TGFX_MAX_PORTS]; @@ -156,38 +157,49 @@ static void tgfx_close(struct input_dev *dev) * tgfx_probe() probes for tg gamepads. */ -static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) +static void tgfx_attach(struct parport *pp) { struct tgfx *tgfx; struct input_dev *input_dev; - struct parport *pp; struct pardevice *pd; - int i, j; - int err; + int i, j, port_idx; + int *n_buttons, n_devs; + struct pardev_cb tgfx_parport_cb; + + for (port_idx = 0; port_idx < TGFX_MAX_PORTS; port_idx++) { + if (tgfx_cfg[port_idx].nargs == 0 || + tgfx_cfg[port_idx].args[0] < 0) + continue; + if (tgfx_cfg[port_idx].args[0] == pp->number) + break; + } - pp = parport_find_number(parport); - if (!pp) { - printk(KERN_ERR "turbografx.c: no such parport\n"); - err = -EINVAL; - goto err_out; + if (port_idx == TGFX_MAX_PORTS) { + pr_debug("Not using parport%d.\n", pp->number); + return; } + n_buttons = tgfx_cfg[port_idx].args + 1; + n_devs = tgfx_cfg[port_idx].nargs - 1; + + memset(&tgfx_parport_cb, 0, sizeof(tgfx_parport_cb)); + tgfx_parport_cb.flags = PARPORT_FLAG_EXCL; - pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); + pd = parport_register_dev_model(pp, "turbografx", &tgfx_parport_cb, + port_idx); if (!pd) { - printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n"); - err = -EBUSY; - goto err_put_pp; + pr_err("parport busy already - lp.o loaded?\n"); + return; } tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL); if (!tgfx) { printk(KERN_ERR "turbografx.c: Not enough memory\n"); - err = -ENOMEM; goto err_unreg_pardev; } mutex_init(&tgfx->sem); tgfx->pd = pd; + tgfx->parportno = pp->number; init_timer(&tgfx->timer); tgfx->timer.data = (long) tgfx; tgfx->timer.function = tgfx_timer; @@ -196,16 +208,14 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) if (n_buttons[i] < 1) continue; - if (n_buttons[i] > 6) { + if (n_buttons[i] > ARRAY_SIZE(tgfx_buttons)) { printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]); - err = -EINVAL; goto err_unreg_devs; } tgfx->dev[i] = input_dev = input_allocate_device(); if (!input_dev) { printk(KERN_ERR "turbografx.c: Not enough memory for input device\n"); - err = -ENOMEM; goto err_unreg_devs; } @@ -234,19 +244,17 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) for (j = 0; j < n_buttons[i]; j++) set_bit(tgfx_buttons[j], input_dev->keybit); - err = input_register_device(tgfx->dev[i]); - if (err) + if (input_register_device(tgfx->dev[i])) goto err_free_dev; } if (!tgfx->sticks) { printk(KERN_ERR "turbografx.c: No valid devices specified\n"); - err = -EINVAL; goto err_free_tgfx; } - parport_put_port(pp); - return tgfx; + tgfx_base[port_idx] = tgfx; + return; err_free_dev: input_free_device(tgfx->dev[i]); @@ -258,15 +266,23 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) kfree(tgfx); err_unreg_pardev: parport_unregister_device(pd); - err_put_pp: - parport_put_port(pp); - err_out: - return ERR_PTR(err); } -static void tgfx_remove(struct tgfx *tgfx) +static void tgfx_detach(struct parport *port) { int i; + struct tgfx *tgfx; + + for (i = 0; i < TGFX_MAX_PORTS; i++) { + if (tgfx_base[i] && tgfx_base[i]->parportno == port->number) + break; + } + + if (i == TGFX_MAX_PORTS) + return; + + tgfx = tgfx_base[i]; + tgfx_base[i] = NULL; for (i = 0; i < TGFX_MAX_DEVICES; i++) if (tgfx->dev[i]) @@ -275,11 +291,17 @@ static void tgfx_remove(struct tgfx *tgfx) kfree(tgfx); } +static struct parport_driver tgfx_parport_driver = { + .name = "turbografx", + .match_port = tgfx_attach, + .detach = tgfx_detach, + .devmodel = true, +}; + static int __init tgfx_init(void) { int i; int have_dev = 0; - int err = 0; for (i = 0; i < TGFX_MAX_PORTS; i++) { if (tgfx_cfg[i].nargs == 0 || tgfx_cfg[i].args[0] < 0) @@ -287,38 +309,21 @@ static int __init tgfx_init(void) if (tgfx_cfg[i].nargs < 2) { printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n"); - err = -EINVAL; - break; - } - - tgfx_base[i] = tgfx_probe(tgfx_cfg[i].args[0], - tgfx_cfg[i].args + 1, - tgfx_cfg[i].nargs - 1); - if (IS_ERR(tgfx_base[i])) { - err = PTR_ERR(tgfx_base[i]); - break; + return -EINVAL; } have_dev = 1; } - if (err) { - while (--i >= 0) - if (tgfx_base[i]) - tgfx_remove(tgfx_base[i]); - return err; - } + if (!have_dev) + return -ENODEV; - return have_dev ? 0 : -ENODEV; + return parport_register_driver(&tgfx_parport_driver); } static void __exit tgfx_exit(void) { - int i; - - for (i = 0; i < TGFX_MAX_PORTS; i++) - if (tgfx_base[i]) - tgfx_remove(tgfx_base[i]); + parport_unregister_driver(&tgfx_parport_driver); } module_init(tgfx_init); diff --git a/kernel/drivers/input/joystick/walkera0701.c b/kernel/drivers/input/joystick/walkera0701.c index b76ac5807..70a893a17 100644 --- a/kernel/drivers/input/joystick/walkera0701.c +++ b/kernel/drivers/input/joystick/walkera0701.c @@ -200,35 +200,39 @@ static void walkera0701_close(struct input_dev *dev) parport_release(w->pardevice); } -static int walkera0701_connect(struct walkera_dev *w, int parport) +static void walkera0701_attach(struct parport *pp) { - int error; + struct pardev_cb walkera0701_parport_cb; + struct walkera_dev *w = &w_dev; - w->parport = parport_find_number(parport); - if (!w->parport) { - pr_err("parport %d does not exist\n", parport); - return -ENODEV; + if (pp->number != walkera0701_pp_no) { + pr_debug("Not using parport%d.\n", pp->number); + return; } - if (w->parport->irq == -1) { + if (pp->irq == -1) { pr_err("parport %d does not have interrupt assigned\n", - parport); - error = -EINVAL; - goto err_put_parport; + pp->number); + return; } - w->pardevice = parport_register_device(w->parport, "walkera0701", - NULL, NULL, walkera0701_irq_handler, - PARPORT_DEV_EXCL, w); + w->parport = pp; + + memset(&walkera0701_parport_cb, 0, sizeof(walkera0701_parport_cb)); + walkera0701_parport_cb.flags = PARPORT_FLAG_EXCL; + walkera0701_parport_cb.irq_func = walkera0701_irq_handler; + walkera0701_parport_cb.private = w; + + w->pardevice = parport_register_dev_model(pp, "walkera0701", + &walkera0701_parport_cb, 0); + if (!w->pardevice) { pr_err("failed to register parport device\n"); - error = -EIO; - goto err_put_parport; + return; } if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT)) { pr_err("failed to negotiate parport mode\n"); - error = -EIO; goto err_unregister_device; } @@ -238,7 +242,6 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) w->input_dev = input_allocate_device(); if (!w->input_dev) { pr_err("failed to allocate input device\n"); - error = -ENOMEM; goto err_unregister_device; } @@ -265,38 +268,46 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) input_set_abs_params(w->input_dev, ABS_RUDDER, -512, 512, 0, 0); input_set_abs_params(w->input_dev, ABS_MISC, -512, 512, 0, 0); - error = input_register_device(w->input_dev); - if (error) { + if (input_register_device(w->input_dev)) { pr_err("failed to register input device\n"); goto err_free_input_dev; } - return 0; + return; err_free_input_dev: input_free_device(w->input_dev); err_unregister_device: parport_unregister_device(w->pardevice); -err_put_parport: - parport_put_port(w->parport); - return error; } -static void walkera0701_disconnect(struct walkera_dev *w) +static void walkera0701_detach(struct parport *port) { + struct walkera_dev *w = &w_dev; + + if (!w->pardevice || w->parport->number != port->number) + return; + input_unregister_device(w->input_dev); parport_unregister_device(w->pardevice); - parport_put_port(w->parport); + w->parport = NULL; } +static struct parport_driver walkera0701_parport_driver = { + .name = "walkera0701", + .match_port = walkera0701_attach, + .detach = walkera0701_detach, + .devmodel = true, +}; + static int __init walkera0701_init(void) { - return walkera0701_connect(&w_dev, walkera0701_pp_no); + return parport_register_driver(&walkera0701_parport_driver); } static void __exit walkera0701_exit(void) { - walkera0701_disconnect(&w_dev); + parport_unregister_driver(&walkera0701_parport_driver); } module_init(walkera0701_init); diff --git a/kernel/drivers/input/joystick/xpad.c b/kernel/drivers/input/joystick/xpad.c index 61c761156..fd4100d56 100644 --- a/kernel/drivers/input/joystick/xpad.c +++ b/kernel/drivers/input/joystick/xpad.c @@ -125,6 +125,7 @@ static const struct xpad_device { { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE }, + { 0x045e, 0x02dd, "Microsoft X-Box One pad (Covert Forces)", 0, XTYPE_XBOXONE }, { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, @@ -204,7 +205,7 @@ static const struct xpad_device { { 0x1bad, 0xf900, "Harmonix Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 }, - { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo", 0, XTYPE_XBOX360 }, @@ -242,7 +243,6 @@ static const signed short xpad_btn_triggers[] = { -1 }; - static const signed short xpad360_btn[] = { /* buttons for x360 controller */ BTN_TL, BTN_TR, /* Button LB/RB */ BTN_MODE, /* The big X button */ @@ -328,9 +328,6 @@ struct usb_xpad { unsigned char *idata; /* input data */ dma_addr_t idata_dma; - struct urb *bulk_out; - unsigned char *bdata; - struct urb *irq_out; /* urb for interrupt out report */ unsigned char *odata; /* output data */ dma_addr_t odata_dma; @@ -344,6 +341,8 @@ struct usb_xpad { int mapping; /* map d-pad to buttons or to axes */ int xtype; /* type of xbox device */ + int pad_nr; /* the order x360 pads were attached */ + const char *name; /* name of the device */ }; /* @@ -355,7 +354,6 @@ struct usb_xpad { * The used report descriptor was taken from ITO Takayukis website: * http://euc.jp/periphs/xbox-controller.ja.html */ - static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) { struct input_dev *dev = xpad->dev; @@ -438,7 +436,16 @@ static void xpad360_process_packet(struct usb_xpad *xpad, input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08); input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01); input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02); - } else { + } + + /* + * This should be a simple else block. However historically + * xbox360w has mapped DPAD to buttons while xbox360 did not. This + * made no sense, but now we can not just switch back and have to + * support both behaviors. + */ + if (!(xpad->mapping & MAP_DPAD_TO_BUTTONS) || + xpad->xtype == XTYPE_XBOX360W) { input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); input_report_abs(dev, ABS_HAT0Y, @@ -488,6 +495,8 @@ static void xpad360_process_packet(struct usb_xpad *xpad, input_sync(dev); } +static void xpad_identify_controller(struct usb_xpad *xpad); + /* * xpad360w_process_packet * @@ -502,14 +511,17 @@ static void xpad360_process_packet(struct usb_xpad *xpad, * 01.1 - Pad state (Bytes 4+) valid * */ - static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) { /* Presence change */ if (data[0] & 0x08) { if (data[1] & 0x80) { xpad->pad_present = 1; - usb_submit_urb(xpad->bulk_out, GFP_ATOMIC); + /* + * Light up the segment corresponding to + * controller number. + */ + xpad_identify_controller(xpad); } else xpad->pad_present = 0; } @@ -666,28 +678,6 @@ exit: __func__, retval); } -static void xpad_bulk_out(struct urb *urb) -{ - struct usb_xpad *xpad = urb->context; - struct device *dev = &xpad->intf->dev; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dev_dbg(dev, "%s - urb shutting down with status: %d\n", - __func__, urb->status); - break; - default: - dev_dbg(dev, "%s - nonzero urb status received: %d\n", - __func__, urb->status); - } -} - static void xpad_irq_out(struct urb *urb) { struct usb_xpad *xpad = urb->context; @@ -778,84 +768,109 @@ static void xpad_deinit_output(struct usb_xpad *xpad) } } +static int xpad_inquiry_pad_presence(struct usb_xpad *xpad) +{ + int retval; + + mutex_lock(&xpad->odata_mutex); + + xpad->odata[0] = 0x08; + xpad->odata[1] = 0x00; + xpad->odata[2] = 0x0F; + xpad->odata[3] = 0xC0; + xpad->odata[4] = 0x00; + xpad->odata[5] = 0x00; + xpad->odata[6] = 0x00; + xpad->odata[7] = 0x00; + xpad->odata[8] = 0x00; + xpad->odata[9] = 0x00; + xpad->odata[10] = 0x00; + xpad->odata[11] = 0x00; + xpad->irq_out->transfer_buffer_length = 12; + + retval = usb_submit_urb(xpad->irq_out, GFP_KERNEL); + + mutex_unlock(&xpad->odata_mutex); + + return retval; +} + #ifdef CONFIG_JOYSTICK_XPAD_FF static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) { struct usb_xpad *xpad = input_get_drvdata(dev); + __u16 strong; + __u16 weak; - if (effect->type == FF_RUMBLE) { - __u16 strong = effect->u.rumble.strong_magnitude; - __u16 weak = effect->u.rumble.weak_magnitude; - - switch (xpad->xtype) { - - case XTYPE_XBOX: - xpad->odata[0] = 0x00; - xpad->odata[1] = 0x06; - xpad->odata[2] = 0x00; - xpad->odata[3] = strong / 256; /* left actuator */ - xpad->odata[4] = 0x00; - xpad->odata[5] = weak / 256; /* right actuator */ - xpad->irq_out->transfer_buffer_length = 6; - - return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - - case XTYPE_XBOX360: - xpad->odata[0] = 0x00; - xpad->odata[1] = 0x08; - xpad->odata[2] = 0x00; - xpad->odata[3] = strong / 256; /* left actuator? */ - xpad->odata[4] = weak / 256; /* right actuator? */ - xpad->odata[5] = 0x00; - xpad->odata[6] = 0x00; - xpad->odata[7] = 0x00; - xpad->irq_out->transfer_buffer_length = 8; - - return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - - case XTYPE_XBOX360W: - xpad->odata[0] = 0x00; - xpad->odata[1] = 0x01; - xpad->odata[2] = 0x0F; - xpad->odata[3] = 0xC0; - xpad->odata[4] = 0x00; - xpad->odata[5] = strong / 256; - xpad->odata[6] = weak / 256; - xpad->odata[7] = 0x00; - xpad->odata[8] = 0x00; - xpad->odata[9] = 0x00; - xpad->odata[10] = 0x00; - xpad->odata[11] = 0x00; - xpad->irq_out->transfer_buffer_length = 12; - - return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - - case XTYPE_XBOXONE: - xpad->odata[0] = 0x09; /* activate rumble */ - xpad->odata[1] = 0x08; - xpad->odata[2] = 0x00; - xpad->odata[3] = 0x08; /* continuous effect */ - xpad->odata[4] = 0x00; /* simple rumble mode */ - xpad->odata[5] = 0x03; /* L and R actuator only */ - xpad->odata[6] = 0x00; /* TODO: LT actuator */ - xpad->odata[7] = 0x00; /* TODO: RT actuator */ - xpad->odata[8] = strong / 256; /* left actuator */ - xpad->odata[9] = weak / 256; /* right actuator */ - xpad->odata[10] = 0x80; /* length of pulse */ - xpad->odata[11] = 0x00; /* stop period of pulse */ - xpad->irq_out->transfer_buffer_length = 12; - - return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - - default: - dev_dbg(&xpad->dev->dev, - "%s - rumble command sent to unsupported xpad type: %d\n", - __func__, xpad->xtype); - return -1; - } + if (effect->type != FF_RUMBLE) + return 0; + + strong = effect->u.rumble.strong_magnitude; + weak = effect->u.rumble.weak_magnitude; + + switch (xpad->xtype) { + case XTYPE_XBOX: + xpad->odata[0] = 0x00; + xpad->odata[1] = 0x06; + xpad->odata[2] = 0x00; + xpad->odata[3] = strong / 256; /* left actuator */ + xpad->odata[4] = 0x00; + xpad->odata[5] = weak / 256; /* right actuator */ + xpad->irq_out->transfer_buffer_length = 6; + break; + + case XTYPE_XBOX360: + xpad->odata[0] = 0x00; + xpad->odata[1] = 0x08; + xpad->odata[2] = 0x00; + xpad->odata[3] = strong / 256; /* left actuator? */ + xpad->odata[4] = weak / 256; /* right actuator? */ + xpad->odata[5] = 0x00; + xpad->odata[6] = 0x00; + xpad->odata[7] = 0x00; + xpad->irq_out->transfer_buffer_length = 8; + break; + + case XTYPE_XBOX360W: + xpad->odata[0] = 0x00; + xpad->odata[1] = 0x01; + xpad->odata[2] = 0x0F; + xpad->odata[3] = 0xC0; + xpad->odata[4] = 0x00; + xpad->odata[5] = strong / 256; + xpad->odata[6] = weak / 256; + xpad->odata[7] = 0x00; + xpad->odata[8] = 0x00; + xpad->odata[9] = 0x00; + xpad->odata[10] = 0x00; + xpad->odata[11] = 0x00; + xpad->irq_out->transfer_buffer_length = 12; + break; + + case XTYPE_XBOXONE: + xpad->odata[0] = 0x09; /* activate rumble */ + xpad->odata[1] = 0x08; + xpad->odata[2] = 0x00; + xpad->odata[3] = 0x08; /* continuous effect */ + xpad->odata[4] = 0x00; /* simple rumble mode */ + xpad->odata[5] = 0x03; /* L and R actuator only */ + xpad->odata[6] = 0x00; /* TODO: LT actuator */ + xpad->odata[7] = 0x00; /* TODO: RT actuator */ + xpad->odata[8] = strong / 256; /* left actuator */ + xpad->odata[9] = weak / 256; /* right actuator */ + xpad->odata[10] = 0x80; /* length of pulse */ + xpad->odata[11] = 0x00; /* stop period of pulse */ + xpad->irq_out->transfer_buffer_length = 12; + break; + + default: + dev_dbg(&xpad->dev->dev, + "%s - rumble command sent to unsupported xpad type: %d\n", + __func__, xpad->xtype); + return -EINVAL; } - return 0; + return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); } static int xpad_init_ff(struct usb_xpad *xpad) @@ -874,6 +889,9 @@ static int xpad_init_ff(struct usb_xpad *xpad) { return 0; } #if defined(CONFIG_JOYSTICK_XPAD_LEDS) #include <linux/leds.h> +#include <linux/idr.h> + +static DEFINE_IDA(xpad_pad_seq); struct xpad_led { char name[16]; @@ -881,17 +899,67 @@ struct xpad_led { struct usb_xpad *xpad; }; +/** + * set the LEDs on Xbox360 / Wireless Controllers + * @param command + * 0: off + * 1: all blink, then previous setting + * 2: 1/top-left blink, then on + * 3: 2/top-right blink, then on + * 4: 3/bottom-left blink, then on + * 5: 4/bottom-right blink, then on + * 6: 1/top-left on + * 7: 2/top-right on + * 8: 3/bottom-left on + * 9: 4/bottom-right on + * 10: rotate + * 11: blink, based on previous setting + * 12: slow blink, based on previous setting + * 13: rotate with two lights + * 14: persistent slow all blink + * 15: blink once, then previous setting + */ static void xpad_send_led_command(struct usb_xpad *xpad, int command) { - if (command >= 0 && command < 14) { - mutex_lock(&xpad->odata_mutex); + command %= 16; + + mutex_lock(&xpad->odata_mutex); + + switch (xpad->xtype) { + case XTYPE_XBOX360: xpad->odata[0] = 0x01; xpad->odata[1] = 0x03; xpad->odata[2] = command; xpad->irq_out->transfer_buffer_length = 3; - usb_submit_urb(xpad->irq_out, GFP_KERNEL); - mutex_unlock(&xpad->odata_mutex); + break; + case XTYPE_XBOX360W: + xpad->odata[0] = 0x00; + xpad->odata[1] = 0x00; + xpad->odata[2] = 0x08; + xpad->odata[3] = 0x40 + command; + xpad->odata[4] = 0x00; + xpad->odata[5] = 0x00; + xpad->odata[6] = 0x00; + xpad->odata[7] = 0x00; + xpad->odata[8] = 0x00; + xpad->odata[9] = 0x00; + xpad->odata[10] = 0x00; + xpad->odata[11] = 0x00; + xpad->irq_out->transfer_buffer_length = 12; + break; } + + usb_submit_urb(xpad->irq_out, GFP_KERNEL); + mutex_unlock(&xpad->odata_mutex); +} + +/* + * Light up the segment corresponding to the pad number on + * Xbox 360 Controllers. + */ +static void xpad_identify_controller(struct usb_xpad *xpad) +{ + xpad_send_led_command(xpad, (xpad->pad_nr % 4) + 2); } static void xpad_led_set(struct led_classdev *led_cdev, @@ -905,22 +973,24 @@ static void xpad_led_set(struct led_classdev *led_cdev, static int xpad_led_probe(struct usb_xpad *xpad) { - static atomic_t led_seq = ATOMIC_INIT(-1); - unsigned long led_no; struct xpad_led *led; struct led_classdev *led_cdev; int error; - if (xpad->xtype != XTYPE_XBOX360) + if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W) return 0; xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL); if (!led) return -ENOMEM; - led_no = atomic_inc_return(&led_seq); + xpad->pad_nr = ida_simple_get(&xpad_pad_seq, 0, 0, GFP_KERNEL); + if (xpad->pad_nr < 0) { + error = xpad->pad_nr; + goto err_free_mem; + } - snprintf(led->name, sizeof(led->name), "xpad%lu", led_no); + snprintf(led->name, sizeof(led->name), "xpad%d", xpad->pad_nr); led->xpad = xpad; led_cdev = &led->led_cdev; @@ -928,18 +998,26 @@ static int xpad_led_probe(struct usb_xpad *xpad) led_cdev->brightness_set = xpad_led_set; error = led_classdev_register(&xpad->udev->dev, led_cdev); - if (error) { - kfree(led); - xpad->led = NULL; - return error; - } + if (error) + goto err_free_id; - /* - * Light up the segment corresponding to controller number - */ - xpad_send_led_command(xpad, (led_no % 4) + 2); + if (xpad->xtype == XTYPE_XBOX360) { + /* + * Light up the segment corresponding to controller + * number on wired devices. On wireless we'll do that + * when they respond to "presence" packet. + */ + xpad_identify_controller(xpad); + } return 0; + +err_free_id: + ida_simple_remove(&xpad_pad_seq, xpad->pad_nr); +err_free_mem: + kfree(led); + xpad->led = NULL; + return error; } static void xpad_led_disconnect(struct usb_xpad *xpad) @@ -948,15 +1026,16 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) if (xpad_led) { led_classdev_unregister(&xpad_led->led_cdev); + ida_simple_remove(&xpad_pad_seq, xpad->pad_nr); kfree(xpad_led); } } #else static int xpad_led_probe(struct usb_xpad *xpad) { return 0; } static void xpad_led_disconnect(struct usb_xpad *xpad) { } +static void xpad_identify_controller(struct usb_xpad *xpad) { } #endif - static int xpad_open(struct input_dev *dev) { struct usb_xpad *xpad = input_get_drvdata(dev); @@ -1016,11 +1095,107 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) } } +static void xpad_deinit_input(struct usb_xpad *xpad) +{ + xpad_led_disconnect(xpad); + input_unregister_device(xpad->dev); +} + +static int xpad_init_input(struct usb_xpad *xpad) +{ + struct input_dev *input_dev; + int i, error; + + input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; + + xpad->dev = input_dev; + input_dev->name = xpad->name; + input_dev->phys = xpad->phys; + usb_to_input_id(xpad->udev, &input_dev->id); + input_dev->dev.parent = &xpad->intf->dev; + + input_set_drvdata(input_dev, xpad); + + input_dev->open = xpad_open; + input_dev->close = xpad_close; + + __set_bit(EV_KEY, input_dev->evbit); + + if (!(xpad->mapping & MAP_STICKS_TO_NULL)) { + __set_bit(EV_ABS, input_dev->evbit); + /* set up axes */ + for (i = 0; xpad_abs[i] >= 0; i++) + xpad_set_up_abs(input_dev, xpad_abs[i]); + } + + /* set up standard buttons */ + for (i = 0; xpad_common_btn[i] >= 0; i++) + __set_bit(xpad_common_btn[i], input_dev->keybit); + + /* set up model-specific ones */ + if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W || + xpad->xtype == XTYPE_XBOXONE) { + for (i = 0; xpad360_btn[i] >= 0; i++) + __set_bit(xpad360_btn[i], input_dev->keybit); + } else { + for (i = 0; xpad_btn[i] >= 0; i++) + __set_bit(xpad_btn[i], input_dev->keybit); + } + + if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { + for (i = 0; xpad_btn_pad[i] >= 0; i++) + __set_bit(xpad_btn_pad[i], input_dev->keybit); + } + + /* + * This should be a simple else block. However historically + * xbox360w has mapped DPAD to buttons while xbox360 did not. This + * made no sense, but now we can not just switch back and have to + * support both behaviors. + */ + if (!(xpad->mapping & MAP_DPAD_TO_BUTTONS) || + xpad->xtype == XTYPE_XBOX360W) { + for (i = 0; xpad_abs_pad[i] >= 0; i++) + xpad_set_up_abs(input_dev, xpad_abs_pad[i]); + } + + if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { + for (i = 0; xpad_btn_triggers[i] >= 0; i++) + __set_bit(xpad_btn_triggers[i], input_dev->keybit); + } else { + for (i = 0; xpad_abs_triggers[i] >= 0; i++) + xpad_set_up_abs(input_dev, xpad_abs_triggers[i]); + } + + error = xpad_init_ff(xpad); + if (error) + goto err_free_input; + + error = xpad_led_probe(xpad); + if (error) + goto err_destroy_ff; + + error = input_register_device(xpad->dev); + if (error) + goto err_disconnect_led; + + return 0; + +err_disconnect_led: + xpad_led_disconnect(xpad); +err_destroy_ff: + input_ff_destroy(input_dev); +err_free_input: + input_free_device(input_dev); + return error; +} + static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(intf); struct usb_xpad *xpad; - struct input_dev *input_dev; struct usb_endpoint_descriptor *ep_irq_in; int ep_irq_in_idx; int i, error; @@ -1042,29 +1217,30 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id } xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!xpad || !input_dev) { - error = -ENOMEM; - goto fail1; - } + if (!xpad) + return -ENOMEM; + + usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); + strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN, GFP_KERNEL, &xpad->idata_dma); if (!xpad->idata) { error = -ENOMEM; - goto fail1; + goto err_free_mem; } xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); if (!xpad->irq_in) { error = -ENOMEM; - goto fail2; + goto err_free_idata; } xpad->udev = udev; xpad->intf = intf; xpad->mapping = xpad_device[i].mapping; xpad->xtype = xpad_device[i].xtype; + xpad->name = xpad_device[i].name; if (xpad->xtype == XTYPE_UNKNOWN) { if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { @@ -1072,8 +1248,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->xtype = XTYPE_XBOX360W; else xpad->xtype = XTYPE_XBOX360; - } else + } else { xpad->xtype = XTYPE_XBOX; + } if (dpad_to_buttons) xpad->mapping |= MAP_DPAD_TO_BUTTONS; @@ -1083,70 +1260,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->mapping |= MAP_STICKS_TO_NULL; } - xpad->dev = input_dev; - usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); - strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); - - input_dev->name = xpad_device[i].name; - input_dev->phys = xpad->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &intf->dev; - - input_set_drvdata(input_dev, xpad); - - input_dev->open = xpad_open; - input_dev->close = xpad_close; - - input_dev->evbit[0] = BIT_MASK(EV_KEY); - - if (!(xpad->mapping & MAP_STICKS_TO_NULL)) { - input_dev->evbit[0] |= BIT_MASK(EV_ABS); - /* set up axes */ - for (i = 0; xpad_abs[i] >= 0; i++) - xpad_set_up_abs(input_dev, xpad_abs[i]); - } - - /* set up standard buttons */ - for (i = 0; xpad_common_btn[i] >= 0; i++) - __set_bit(xpad_common_btn[i], input_dev->keybit); - - /* set up model-specific ones */ - if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W || - xpad->xtype == XTYPE_XBOXONE) { - for (i = 0; xpad360_btn[i] >= 0; i++) - __set_bit(xpad360_btn[i], input_dev->keybit); - } else { - for (i = 0; xpad_btn[i] >= 0; i++) - __set_bit(xpad_btn[i], input_dev->keybit); - } - - if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { - for (i = 0; xpad_btn_pad[i] >= 0; i++) - __set_bit(xpad_btn_pad[i], input_dev->keybit); - } else { - for (i = 0; xpad_abs_pad[i] >= 0; i++) - xpad_set_up_abs(input_dev, xpad_abs_pad[i]); - } - - if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { - for (i = 0; xpad_btn_triggers[i] >= 0; i++) - __set_bit(xpad_btn_triggers[i], input_dev->keybit); - } else { - for (i = 0; xpad_abs_triggers[i] >= 0; i++) - xpad_set_up_abs(input_dev, xpad_abs_triggers[i]); - } - error = xpad_init_output(intf, xpad); if (error) - goto fail3; - - error = xpad_init_ff(xpad); - if (error) - goto fail4; - - error = xpad_led_probe(xpad); - if (error) - goto fail5; + goto err_free_in_urb; /* Xbox One controller has in/out endpoints swapped. */ ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0; @@ -1159,59 +1275,13 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->irq_in->transfer_dma = xpad->idata_dma; xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - error = input_register_device(xpad->dev); - if (error) - goto fail6; - usb_set_intfdata(intf, xpad); - if (xpad->xtype == XTYPE_XBOX360W) { - /* - * Setup the message to set the LEDs on the - * controller when it shows up - */ - xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL); - if (!xpad->bulk_out) { - error = -ENOMEM; - goto fail7; - } - - xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL); - if (!xpad->bdata) { - error = -ENOMEM; - goto fail8; - } - - xpad->bdata[2] = 0x08; - switch (intf->cur_altsetting->desc.bInterfaceNumber) { - case 0: - xpad->bdata[3] = 0x42; - break; - case 2: - xpad->bdata[3] = 0x43; - break; - case 4: - xpad->bdata[3] = 0x44; - break; - case 6: - xpad->bdata[3] = 0x45; - } - - ep_irq_in = &intf->cur_altsetting->endpoint[1].desc; - if (usb_endpoint_is_bulk_out(ep_irq_in)) { - usb_fill_bulk_urb(xpad->bulk_out, udev, - usb_sndbulkpipe(udev, - ep_irq_in->bEndpointAddress), - xpad->bdata, XPAD_PKT_LEN, - xpad_bulk_out, xpad); - } else { - usb_fill_int_urb(xpad->bulk_out, udev, - usb_sndintpipe(udev, - ep_irq_in->bEndpointAddress), - xpad->bdata, XPAD_PKT_LEN, - xpad_bulk_out, xpad, 0); - } + error = xpad_init_input(xpad); + if (error) + goto err_deinit_output; + if (xpad->xtype == XTYPE_XBOX360W) { /* * Submit the int URB immediately rather than waiting for open * because we get status messages from the device whether @@ -1222,22 +1292,32 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->irq_in->dev = xpad->udev; error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); if (error) - goto fail9; - } + goto err_deinit_input; + /* + * Send presence packet. + * This will force the controller to resend connection packets. + * This is useful in the case we activate the module after the + * adapter has been plugged in, as it won't automatically + * send us info about the controllers. + */ + error = xpad_inquiry_pad_presence(xpad); + if (error) + goto err_kill_in_urb; + } return 0; - fail9: kfree(xpad->bdata); - fail8: usb_free_urb(xpad->bulk_out); - fail7: input_unregister_device(input_dev); - input_dev = NULL; - fail6: xpad_led_disconnect(xpad); - fail5: if (input_dev) - input_ff_destroy(input_dev); - fail4: xpad_deinit_output(xpad); - fail3: usb_free_urb(xpad->irq_in); - fail2: usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); - fail1: input_free_device(input_dev); +err_kill_in_urb: + usb_kill_urb(xpad->irq_in); +err_deinit_input: + xpad_deinit_input(xpad); +err_deinit_output: + xpad_deinit_output(xpad); +err_free_in_urb: + usb_free_urb(xpad->irq_in); +err_free_idata: + usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); +err_free_mem: kfree(xpad); return error; @@ -1247,13 +1327,10 @@ static void xpad_disconnect(struct usb_interface *intf) { struct usb_xpad *xpad = usb_get_intfdata (intf); - xpad_led_disconnect(xpad); - input_unregister_device(xpad->dev); + xpad_deinit_input(xpad); xpad_deinit_output(xpad); if (xpad->xtype == XTYPE_XBOX360W) { - usb_kill_urb(xpad->bulk_out); - usb_free_urb(xpad->bulk_out); usb_kill_urb(xpad->irq_in); } @@ -1261,7 +1338,6 @@ static void xpad_disconnect(struct usb_interface *intf) usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); - kfree(xpad->bdata); kfree(xpad); usb_set_intfdata(intf, NULL); diff --git a/kernel/drivers/input/joystick/zhenhua.c b/kernel/drivers/input/joystick/zhenhua.c index 30af2e8c6..4a8258bf1 100644 --- a/kernel/drivers/input/joystick/zhenhua.c +++ b/kernel/drivers/input/joystick/zhenhua.c @@ -47,6 +47,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/bitrev.h> #include <linux/input.h> #include <linux/serio.h> @@ -72,16 +73,6 @@ struct zhenhua { char phys[32]; }; - -/* bits in all incoming bytes needs to be "reversed" */ -static int zhenhua_bitreverse(int x) -{ - x = ((x & 0xaa) >> 1) | ((x & 0x55) << 1); - x = ((x & 0xcc) >> 2) | ((x & 0x33) << 2); - x = ((x & 0xf0) >> 4) | ((x & 0x0f) << 4); - return x; -} - /* * zhenhua_process_packet() decodes packets the driver receives from the * RC transmitter. It updates the data accordingly. @@ -120,7 +111,7 @@ static irqreturn_t zhenhua_interrupt(struct serio *serio, unsigned char data, un return IRQ_HANDLED; /* wrong MSB -- ignore this byte */ if (zhenhua->idx < ZHENHUA_MAX_LENGTH) - zhenhua->data[zhenhua->idx++] = zhenhua_bitreverse(data); + zhenhua->data[zhenhua->idx++] = bitrev8(data); if (zhenhua->idx == ZHENHUA_MAX_LENGTH) { zhenhua_process_packet(zhenhua); |