diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:51:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:51:43 -0400 |
commit | 393bfca19ecdce60a8d9a4d2577cac11ca924a25 (patch) | |
tree | a609269ca3332b8f2f7b2b4a2c96f7d824c0e639 /drivers/input | |
parent | df6d3916f3b7b7e2067567a256dd4f0c1ea854a2 (diff) | |
parent | ba0acb5ee318901646f82c134cca2e4de0c43934 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/dtor/input
* master.kernel.org:/pub/scm/linux/kernel/git/dtor/input:
Input: move USB miscellaneous devices under drivers/input/misc
Input: move USB mice under drivers/input/mouse
Input: move USB gamepads under drivers/input/joystick
Input: move USB touchscreens under drivers/input/touchscreen
Input: move USB tablets under drivers/input/tablet
Input: i8042 - fix AUX port detection with some chips
Input: aaed2000_kbd - convert to use polldev library
Input: drivers/usb/input - usb_buffer_free() cleanup
Input: synaptics - don't complain about failed resets
Input: pull input.h into uinpit.h
Input: drivers/usb/input - fix sparse warnings (signedness)
Input: evdev - fix some sparse warnings (signedness, shadowing)
Input: drivers/joystick - fix various sparse warnings
Input: force feedback - make sure effect is present before playing
Diffstat (limited to 'drivers/input')
42 files changed, 11206 insertions, 112 deletions
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 96232313b1b9..0e9b69535ad6 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig | |||
@@ -153,6 +153,8 @@ source "drivers/input/mouse/Kconfig" | |||
153 | 153 | ||
154 | source "drivers/input/joystick/Kconfig" | 154 | source "drivers/input/joystick/Kconfig" |
155 | 155 | ||
156 | source "drivers/input/tablet/Kconfig" | ||
157 | |||
156 | source "drivers/input/touchscreen/Kconfig" | 158 | source "drivers/input/touchscreen/Kconfig" |
157 | 159 | ||
158 | source "drivers/input/misc/Kconfig" | 160 | source "drivers/input/misc/Kconfig" |
diff --git a/drivers/input/Makefile b/drivers/input/Makefile index b4cd10653c4f..8a2dd987546c 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_INPUT_EVBUG) += evbug.o | |||
18 | obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/ | 18 | obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/ |
19 | obj-$(CONFIG_INPUT_MOUSE) += mouse/ | 19 | obj-$(CONFIG_INPUT_MOUSE) += mouse/ |
20 | obj-$(CONFIG_INPUT_JOYSTICK) += joystick/ | 20 | obj-$(CONFIG_INPUT_JOYSTICK) += joystick/ |
21 | obj-$(CONFIG_INPUT_TABLET) += tablet/ | ||
21 | obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ | 22 | obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ |
22 | obj-$(CONFIG_INPUT_MISC) += misc/ | 23 | obj-$(CONFIG_INPUT_MISC) += misc/ |
23 | 24 | ||
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index be3dbc1ae67d..55a72592704c 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -511,7 +511,7 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | |||
511 | 511 | ||
512 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | 512 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { |
513 | 513 | ||
514 | long *bits; | 514 | unsigned long *bits; |
515 | int len; | 515 | int len; |
516 | 516 | ||
517 | switch (_IOC_NR(cmd) & EV_MAX) { | 517 | switch (_IOC_NR(cmd) & EV_MAX) { |
@@ -556,7 +556,7 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | |||
556 | 556 | ||
557 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | 557 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { |
558 | 558 | ||
559 | int t = _IOC_NR(cmd) & ABS_MAX; | 559 | t = _IOC_NR(cmd) & ABS_MAX; |
560 | 560 | ||
561 | abs.value = dev->abs[t]; | 561 | abs.value = dev->abs[t]; |
562 | abs.minimum = dev->absmin[t]; | 562 | abs.minimum = dev->absmin[t]; |
@@ -576,7 +576,7 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | |||
576 | 576 | ||
577 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | 577 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
578 | 578 | ||
579 | int t = _IOC_NR(cmd) & ABS_MAX; | 579 | t = _IOC_NR(cmd) & ABS_MAX; |
580 | 580 | ||
581 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | 581 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) |
582 | return -EFAULT; | 582 | return -EFAULT; |
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 783b3412cead..eebc72465fc9 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c | |||
@@ -281,7 +281,8 @@ int input_ff_event(struct input_dev *dev, unsigned int type, | |||
281 | break; | 281 | break; |
282 | 282 | ||
283 | default: | 283 | default: |
284 | ff->playback(dev, code, value); | 284 | if (check_effect_access(ff, code, NULL) == 0) |
285 | ff->playback(dev, code, value); | ||
285 | break; | 286 | break; |
286 | } | 287 | } |
287 | 288 | ||
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 271263443c37..82f563e24fdb 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig | |||
@@ -2,7 +2,7 @@ | |||
2 | # Joystick driver configuration | 2 | # Joystick driver configuration |
3 | # | 3 | # |
4 | menuconfig INPUT_JOYSTICK | 4 | menuconfig INPUT_JOYSTICK |
5 | bool "Joysticks" | 5 | bool "Joysticks/Gamepads" |
6 | help | 6 | help |
7 | If you have a joystick, 6dof controller, gamepad, steering wheel, | 7 | If you have a joystick, 6dof controller, gamepad, steering wheel, |
8 | weapon control system or something like that you can say Y here | 8 | weapon control system or something like that you can say Y here |
@@ -196,7 +196,7 @@ config JOYSTICK_TWIDJOY | |||
196 | config JOYSTICK_DB9 | 196 | config JOYSTICK_DB9 |
197 | tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads" | 197 | tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads" |
198 | depends on PARPORT | 198 | depends on PARPORT |
199 | ---help--- | 199 | help |
200 | Say Y here if you have a Sega Master System gamepad, Sega Genesis | 200 | Say Y here if you have a Sega Master System gamepad, Sega Genesis |
201 | gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga, | 201 | gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga, |
202 | Commodore, Amstrad CPC joystick connected to your parallel port. | 202 | Commodore, Amstrad CPC joystick connected to your parallel port. |
@@ -253,4 +253,18 @@ config JOYSTICK_JOYDUMP | |||
253 | To compile this driver as a module, choose M here: the | 253 | To compile this driver as a module, choose M here: the |
254 | module will be called joydump. | 254 | module will be called joydump. |
255 | 255 | ||
256 | config JOYSTICK_XPAD | ||
257 | tristate "X-Box gamepad support" | ||
258 | select USB | ||
259 | help | ||
260 | Say Y here if you want to use the X-Box pad with your computer. | ||
261 | Make sure to say Y to "Joystick support" (CONFIG_INPUT_JOYDEV) | ||
262 | and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well. | ||
263 | |||
264 | For information about how to connect the X-Box pad to USB, see | ||
265 | <file:Documentation/input/xpad.txt>. | ||
266 | |||
267 | To compile this driver as a module, choose M here: the | ||
268 | module will be called xpad. | ||
269 | |||
256 | endif | 270 | endif |
diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile index 5231f6ff75b8..e855abb0cc51 100644 --- a/drivers/input/joystick/Makefile +++ b/drivers/input/joystick/Makefile | |||
@@ -26,5 +26,6 @@ obj-$(CONFIG_JOYSTICK_TMDC) += tmdc.o | |||
26 | obj-$(CONFIG_JOYSTICK_TURBOGRAFX) += turbografx.o | 26 | obj-$(CONFIG_JOYSTICK_TURBOGRAFX) += turbografx.o |
27 | obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o | 27 | obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o |
28 | obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o | 28 | obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o |
29 | obj-$(CONFIG_JOYSTICK_XPAD) += xpad.o | ||
29 | 30 | ||
30 | obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/ | 31 | obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/ |
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 1c1afb5d4684..bdd157c1ebf8 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -53,7 +53,7 @@ MODULE_LICENSE("GPL"); | |||
53 | #define ANALOG_PORTS 16 | 53 | #define ANALOG_PORTS 16 |
54 | 54 | ||
55 | static char *js[ANALOG_PORTS]; | 55 | static char *js[ANALOG_PORTS]; |
56 | static int js_nargs; | 56 | static unsigned int js_nargs; |
57 | static int analog_options[ANALOG_PORTS]; | 57 | static int analog_options[ANALOG_PORTS]; |
58 | module_param_array_named(map, js, charp, &js_nargs, 0); | 58 | module_param_array_named(map, js, charp, &js_nargs, 0); |
59 | MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities"); | 59 | MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities"); |
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index c27593bf9978..86ad1027e12a 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c | |||
@@ -46,17 +46,17 @@ MODULE_LICENSE("GPL"); | |||
46 | 46 | ||
47 | struct db9_config { | 47 | struct db9_config { |
48 | int args[2]; | 48 | int args[2]; |
49 | int nargs; | 49 | unsigned int nargs; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | #define DB9_MAX_PORTS 3 | 52 | #define DB9_MAX_PORTS 3 |
53 | static struct db9_config db9[DB9_MAX_PORTS] __initdata; | 53 | static struct db9_config db9_cfg[DB9_MAX_PORTS] __initdata; |
54 | 54 | ||
55 | module_param_array_named(dev, db9[0].args, int, &db9[0].nargs, 0); | 55 | module_param_array_named(dev, db9_cfg[0].args, int, &db9_cfg[0].nargs, 0); |
56 | MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)"); | 56 | MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)"); |
57 | module_param_array_named(dev2, db9[1].args, int, &db9[0].nargs, 0); | 57 | module_param_array_named(dev2, db9_cfg[1].args, int, &db9_cfg[0].nargs, 0); |
58 | MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)"); | 58 | MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)"); |
59 | module_param_array_named(dev3, db9[2].args, int, &db9[2].nargs, 0); | 59 | module_param_array_named(dev3, db9_cfg[2].args, int, &db9_cfg[2].nargs, 0); |
60 | MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)"); | 60 | MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)"); |
61 | 61 | ||
62 | #define DB9_ARG_PARPORT 0 | 62 | #define DB9_ARG_PARPORT 0 |
@@ -680,17 +680,17 @@ static int __init db9_init(void) | |||
680 | int err = 0; | 680 | int err = 0; |
681 | 681 | ||
682 | for (i = 0; i < DB9_MAX_PORTS; i++) { | 682 | for (i = 0; i < DB9_MAX_PORTS; i++) { |
683 | if (db9[i].nargs == 0 || db9[i].args[DB9_ARG_PARPORT] < 0) | 683 | if (db9_cfg[i].nargs == 0 || db9_cfg[i].args[DB9_ARG_PARPORT] < 0) |
684 | continue; | 684 | continue; |
685 | 685 | ||
686 | if (db9[i].nargs < 2) { | 686 | if (db9_cfg[i].nargs < 2) { |
687 | printk(KERN_ERR "db9.c: Device type must be specified.\n"); | 687 | printk(KERN_ERR "db9.c: Device type must be specified.\n"); |
688 | err = -EINVAL; | 688 | err = -EINVAL; |
689 | break; | 689 | break; |
690 | } | 690 | } |
691 | 691 | ||
692 | db9_base[i] = db9_probe(db9[i].args[DB9_ARG_PARPORT], | 692 | db9_base[i] = db9_probe(db9_cfg[i].args[DB9_ARG_PARPORT], |
693 | db9[i].args[DB9_ARG_MODE]); | 693 | db9_cfg[i].args[DB9_ARG_MODE]); |
694 | if (IS_ERR(db9_base[i])) { | 694 | if (IS_ERR(db9_base[i])) { |
695 | err = PTR_ERR(db9_base[i]); | 695 | err = PTR_ERR(db9_base[i]); |
696 | break; | 696 | break; |
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index c71b58fe225d..1a452e0e5f25 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c | |||
@@ -48,16 +48,16 @@ MODULE_LICENSE("GPL"); | |||
48 | 48 | ||
49 | struct gc_config { | 49 | struct gc_config { |
50 | int args[GC_MAX_DEVICES + 1]; | 50 | int args[GC_MAX_DEVICES + 1]; |
51 | int nargs; | 51 | unsigned int nargs; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static struct gc_config gc[GC_MAX_PORTS] __initdata; | 54 | static struct gc_config gc_cfg[GC_MAX_PORTS] __initdata; |
55 | 55 | ||
56 | module_param_array_named(map, gc[0].args, int, &gc[0].nargs, 0); | 56 | module_param_array_named(map, gc_cfg[0].args, int, &gc_cfg[0].nargs, 0); |
57 | MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)"); | 57 | MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)"); |
58 | module_param_array_named(map2, gc[1].args, int, &gc[1].nargs, 0); | 58 | module_param_array_named(map2, gc_cfg[1].args, int, &gc_cfg[1].nargs, 0); |
59 | MODULE_PARM_DESC(map2, "Describes second set of devices"); | 59 | MODULE_PARM_DESC(map2, "Describes second set of devices"); |
60 | module_param_array_named(map3, gc[2].args, int, &gc[2].nargs, 0); | 60 | module_param_array_named(map3, gc_cfg[2].args, int, &gc_cfg[2].nargs, 0); |
61 | MODULE_PARM_DESC(map3, "Describes third set of devices"); | 61 | MODULE_PARM_DESC(map3, "Describes third set of devices"); |
62 | 62 | ||
63 | /* see also gs_psx_delay parameter in PSX support section */ | 63 | /* see also gs_psx_delay parameter in PSX support section */ |
@@ -810,16 +810,17 @@ static int __init gc_init(void) | |||
810 | int err = 0; | 810 | int err = 0; |
811 | 811 | ||
812 | for (i = 0; i < GC_MAX_PORTS; i++) { | 812 | for (i = 0; i < GC_MAX_PORTS; i++) { |
813 | if (gc[i].nargs == 0 || gc[i].args[0] < 0) | 813 | if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0) |
814 | continue; | 814 | continue; |
815 | 815 | ||
816 | if (gc[i].nargs < 2) { | 816 | if (gc_cfg[i].nargs < 2) { |
817 | printk(KERN_ERR "gamecon.c: at least one device must be specified\n"); | 817 | printk(KERN_ERR "gamecon.c: at least one device must be specified\n"); |
818 | err = -EINVAL; | 818 | err = -EINVAL; |
819 | break; | 819 | break; |
820 | } | 820 | } |
821 | 821 | ||
822 | gc_base[i] = gc_probe(gc[i].args[0], gc[i].args + 1, gc[i].nargs - 1); | 822 | gc_base[i] = gc_probe(gc_cfg[i].args[0], |
823 | gc_cfg[i].args + 1, gc_cfg[i].nargs - 1); | ||
823 | if (IS_ERR(gc_base[i])) { | 824 | if (IS_ERR(gc_base[i])) { |
824 | err = PTR_ERR(gc_base[i]); | 825 | err = PTR_ERR(gc_base[i]); |
825 | break; | 826 | break; |
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index dadcf4fb92ae..40a853ac21c7 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h | |||
@@ -124,7 +124,7 @@ struct iforce { | |||
124 | /* Buffer used for asynchronous sending of bytes to the device */ | 124 | /* Buffer used for asynchronous sending of bytes to the device */ |
125 | struct circ_buf xmit; | 125 | struct circ_buf xmit; |
126 | unsigned char xmit_data[XMIT_SIZE]; | 126 | unsigned char xmit_data[XMIT_SIZE]; |
127 | long xmit_flags[1]; | 127 | unsigned long xmit_flags[1]; |
128 | 128 | ||
129 | /* Force Feedback */ | 129 | /* Force Feedback */ |
130 | wait_queue_head_t wait; | 130 | wait_queue_head_t wait; |
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index 0f2c60823b0b..8381c6f14373 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c | |||
@@ -48,16 +48,16 @@ MODULE_LICENSE("GPL"); | |||
48 | 48 | ||
49 | struct tgfx_config { | 49 | struct tgfx_config { |
50 | int args[TGFX_MAX_DEVICES + 1]; | 50 | int args[TGFX_MAX_DEVICES + 1]; |
51 | int nargs; | 51 | unsigned int nargs; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static struct tgfx_config tgfx[TGFX_MAX_PORTS] __initdata; | 54 | static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS] __initdata; |
55 | 55 | ||
56 | module_param_array_named(map, tgfx[0].args, int, &tgfx[0].nargs, 0); | 56 | module_param_array_named(map, tgfx_cfg[0].args, int, &tgfx_cfg[0].nargs, 0); |
57 | MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>"); | 57 | MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>"); |
58 | module_param_array_named(map2, tgfx[1].args, int, &tgfx[1].nargs, 0); | 58 | module_param_array_named(map2, tgfx_cfg[1].args, int, &tgfx_cfg[1].nargs, 0); |
59 | MODULE_PARM_DESC(map2, "Describes second set of devices"); | 59 | MODULE_PARM_DESC(map2, "Describes second set of devices"); |
60 | module_param_array_named(map3, tgfx[2].args, int, &tgfx[2].nargs, 0); | 60 | module_param_array_named(map3, tgfx_cfg[2].args, int, &tgfx_cfg[2].nargs, 0); |
61 | MODULE_PARM_DESC(map3, "Describes third set of devices"); | 61 | MODULE_PARM_DESC(map3, "Describes third set of devices"); |
62 | 62 | ||
63 | #define TGFX_REFRESH_TIME HZ/100 /* 10 ms */ | 63 | #define TGFX_REFRESH_TIME HZ/100 /* 10 ms */ |
@@ -283,16 +283,18 @@ static int __init tgfx_init(void) | |||
283 | int err = 0; | 283 | int err = 0; |
284 | 284 | ||
285 | for (i = 0; i < TGFX_MAX_PORTS; i++) { | 285 | for (i = 0; i < TGFX_MAX_PORTS; i++) { |
286 | if (tgfx[i].nargs == 0 || tgfx[i].args[0] < 0) | 286 | if (tgfx_cfg[i].nargs == 0 || tgfx_cfg[i].args[0] < 0) |
287 | continue; | 287 | continue; |
288 | 288 | ||
289 | if (tgfx[i].nargs < 2) { | 289 | if (tgfx_cfg[i].nargs < 2) { |
290 | printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n"); | 290 | printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n"); |
291 | err = -EINVAL; | 291 | err = -EINVAL; |
292 | break; | 292 | break; |
293 | } | 293 | } |
294 | 294 | ||
295 | tgfx_base[i] = tgfx_probe(tgfx[i].args[0], tgfx[i].args + 1, tgfx[i].nargs - 1); | 295 | tgfx_base[i] = tgfx_probe(tgfx_cfg[i].args[0], |
296 | tgfx_cfg[i].args + 1, | ||
297 | tgfx_cfg[i].nargs - 1); | ||
296 | if (IS_ERR(tgfx_base[i])) { | 298 | if (IS_ERR(tgfx_base[i])) { |
297 | err = PTR_ERR(tgfx_base[i]); | 299 | err = PTR_ERR(tgfx_base[i]); |
298 | break; | 300 | break; |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c new file mode 100644 index 000000000000..8c8cd95a6989 --- /dev/null +++ b/drivers/input/joystick/xpad.c | |||
@@ -0,0 +1,433 @@ | |||
1 | /* | ||
2 | * X-Box gamepad - v0.0.6 | ||
3 | * | ||
4 | * Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de> | ||
5 | * 2004 Oliver Schwartz <Oliver.Schwartz@gmx.de>, | ||
6 | * Steven Toth <steve@toth.demon.co.uk>, | ||
7 | * Franz Lehner <franz@caos.at>, | ||
8 | * Ivan Hawkes <blackhawk@ivanhawkes.com> | ||
9 | * 2005 Dominic Cerquetti <binary1230@yahoo.com> | ||
10 | * 2006 Adam Buchbinder <adam.buchbinder@gmail.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License as | ||
14 | * published by the Free Software Foundation; either version 2 of | ||
15 | * the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | * | ||
27 | * This driver is based on: | ||
28 | * - information from http://euc.jp/periphs/xbox-controller.ja.html | ||
29 | * - the iForce driver drivers/char/joystick/iforce.c | ||
30 | * - the skeleton-driver drivers/usb/usb-skeleton.c | ||
31 | * | ||
32 | * Thanks to: | ||
33 | * - ITO Takayuki for providing essential xpad information on his website | ||
34 | * - Vojtech Pavlik - iforce driver / input subsystem | ||
35 | * - Greg Kroah-Hartman - usb-skeleton driver | ||
36 | * - XBOX Linux project - extra USB id's | ||
37 | * | ||
38 | * TODO: | ||
39 | * - fine tune axes (especially trigger axes) | ||
40 | * - fix "analog" buttons (reported as digital now) | ||
41 | * - get rumble working | ||
42 | * - need USB IDs for other dance pads | ||
43 | * | ||
44 | * History: | ||
45 | * | ||
46 | * 2002-06-27 - 0.0.1 : first version, just said "XBOX HID controller" | ||
47 | * | ||
48 | * 2002-07-02 - 0.0.2 : basic working version | ||
49 | * - all axes and 9 of the 10 buttons work (german InterAct device) | ||
50 | * - the black button does not work | ||
51 | * | ||
52 | * 2002-07-14 - 0.0.3 : rework by Vojtech Pavlik | ||
53 | * - indentation fixes | ||
54 | * - usb + input init sequence fixes | ||
55 | * | ||
56 | * 2002-07-16 - 0.0.4 : minor changes, merge with Vojtech's v0.0.3 | ||
57 | * - verified the lack of HID and report descriptors | ||
58 | * - verified that ALL buttons WORK | ||
59 | * - fixed d-pad to axes mapping | ||
60 | * | ||
61 | * 2002-07-17 - 0.0.5 : simplified d-pad handling | ||
62 | * | ||
63 | * 2004-10-02 - 0.0.6 : DDR pad support | ||
64 | * - borrowed from the XBOX linux kernel | ||
65 | * - USB id's for commonly used dance pads are present | ||
66 | * - dance pads will map D-PAD to buttons, not axes | ||
67 | * - pass the module paramater 'dpad_to_buttons' to force | ||
68 | * the D-PAD to map to buttons if your pad is not detected | ||
69 | */ | ||
70 | |||
71 | #include <linux/kernel.h> | ||
72 | #include <linux/init.h> | ||
73 | #include <linux/slab.h> | ||
74 | #include <linux/stat.h> | ||
75 | #include <linux/module.h> | ||
76 | #include <linux/moduleparam.h> | ||
77 | #include <linux/usb/input.h> | ||
78 | |||
79 | #define DRIVER_VERSION "v0.0.6" | ||
80 | #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" | ||
81 | #define DRIVER_DESC "X-Box pad driver" | ||
82 | |||
83 | #define XPAD_PKT_LEN 32 | ||
84 | |||
85 | /* xbox d-pads should map to buttons, as is required for DDR pads | ||
86 | but we map them to axes when possible to simplify things */ | ||
87 | #define MAP_DPAD_TO_BUTTONS 0 | ||
88 | #define MAP_DPAD_TO_AXES 1 | ||
89 | #define MAP_DPAD_UNKNOWN -1 | ||
90 | |||
91 | static int dpad_to_buttons; | ||
92 | module_param(dpad_to_buttons, bool, S_IRUGO); | ||
93 | MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); | ||
94 | |||
95 | static const struct xpad_device { | ||
96 | u16 idVendor; | ||
97 | u16 idProduct; | ||
98 | char *name; | ||
99 | u8 dpad_mapping; | ||
100 | } xpad_device[] = { | ||
101 | { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES }, | ||
102 | { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES }, | ||
103 | { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES }, | ||
104 | { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES }, | ||
105 | { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS }, | ||
106 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES }, | ||
107 | { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES }, | ||
108 | { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES }, | ||
109 | { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES }, | ||
110 | { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES }, | ||
111 | { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES }, | ||
112 | { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES }, | ||
113 | { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES }, | ||
114 | { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES }, | ||
115 | { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS }, | ||
116 | { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES }, | ||
117 | { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS }, | ||
118 | { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES }, | ||
119 | { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES }, | ||
120 | { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES }, | ||
121 | { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES }, | ||
122 | { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES}, | ||
123 | { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES }, | ||
124 | { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES }, | ||
125 | { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES }, | ||
126 | { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES }, | ||
127 | { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES }, | ||
128 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES }, | ||
129 | { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES }, | ||
130 | { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS }, | ||
131 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS }, | ||
132 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES }, | ||
133 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN } | ||
134 | }; | ||
135 | |||
136 | static const signed short xpad_btn[] = { | ||
137 | BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, /* "analog" buttons */ | ||
138 | BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */ | ||
139 | -1 /* terminating entry */ | ||
140 | }; | ||
141 | |||
142 | /* only used if MAP_DPAD_TO_BUTTONS */ | ||
143 | static const signed short xpad_btn_pad[] = { | ||
144 | BTN_LEFT, BTN_RIGHT, /* d-pad left, right */ | ||
145 | BTN_0, BTN_1, /* d-pad up, down (XXX names??) */ | ||
146 | -1 /* terminating entry */ | ||
147 | }; | ||
148 | |||
149 | static const signed short xpad_abs[] = { | ||
150 | ABS_X, ABS_Y, /* left stick */ | ||
151 | ABS_RX, ABS_RY, /* right stick */ | ||
152 | ABS_Z, ABS_RZ, /* triggers left/right */ | ||
153 | -1 /* terminating entry */ | ||
154 | }; | ||
155 | |||
156 | /* only used if MAP_DPAD_TO_AXES */ | ||
157 | static const signed short xpad_abs_pad[] = { | ||
158 | ABS_HAT0X, ABS_HAT0Y, /* d-pad axes */ | ||
159 | -1 /* terminating entry */ | ||
160 | }; | ||
161 | |||
162 | static struct usb_device_id xpad_table [] = { | ||
163 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ | ||
164 | { } | ||
165 | }; | ||
166 | |||
167 | MODULE_DEVICE_TABLE (usb, xpad_table); | ||
168 | |||
169 | struct usb_xpad { | ||
170 | struct input_dev *dev; /* input device interface */ | ||
171 | struct usb_device *udev; /* usb device */ | ||
172 | |||
173 | struct urb *irq_in; /* urb for interrupt in report */ | ||
174 | unsigned char *idata; /* input data */ | ||
175 | dma_addr_t idata_dma; | ||
176 | |||
177 | char phys[65]; /* physical device path */ | ||
178 | |||
179 | int dpad_mapping; /* map d-pad to buttons or to axes */ | ||
180 | }; | ||
181 | |||
182 | /* | ||
183 | * xpad_process_packet | ||
184 | * | ||
185 | * Completes a request by converting the data into events for the | ||
186 | * input subsystem. | ||
187 | * | ||
188 | * The used report descriptor was taken from ITO Takayukis website: | ||
189 | * http://euc.jp/periphs/xbox-controller.ja.html | ||
190 | */ | ||
191 | |||
192 | static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) | ||
193 | { | ||
194 | struct input_dev *dev = xpad->dev; | ||
195 | |||
196 | /* left stick */ | ||
197 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); | ||
198 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); | ||
199 | |||
200 | /* right stick */ | ||
201 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); | ||
202 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); | ||
203 | |||
204 | /* triggers left/right */ | ||
205 | input_report_abs(dev, ABS_Z, data[10]); | ||
206 | input_report_abs(dev, ABS_RZ, data[11]); | ||
207 | |||
208 | /* digital pad */ | ||
209 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { | ||
210 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); | ||
211 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); | ||
212 | } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { | ||
213 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); | ||
214 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); | ||
215 | input_report_key(dev, BTN_0, data[2] & 0x01); // up | ||
216 | input_report_key(dev, BTN_1, data[2] & 0x02); // down | ||
217 | } | ||
218 | |||
219 | /* start/back buttons and stick press left/right */ | ||
220 | input_report_key(dev, BTN_START, data[2] & 0x10); | ||
221 | input_report_key(dev, BTN_BACK, data[2] & 0x20); | ||
222 | input_report_key(dev, BTN_THUMBL, data[2] & 0x40); | ||
223 | input_report_key(dev, BTN_THUMBR, data[2] & 0x80); | ||
224 | |||
225 | /* "analog" buttons A, B, X, Y */ | ||
226 | input_report_key(dev, BTN_A, data[4]); | ||
227 | input_report_key(dev, BTN_B, data[5]); | ||
228 | input_report_key(dev, BTN_X, data[6]); | ||
229 | input_report_key(dev, BTN_Y, data[7]); | ||
230 | |||
231 | /* "analog" buttons black, white */ | ||
232 | input_report_key(dev, BTN_C, data[8]); | ||
233 | input_report_key(dev, BTN_Z, data[9]); | ||
234 | |||
235 | input_sync(dev); | ||
236 | } | ||
237 | |||
238 | static void xpad_irq_in(struct urb *urb) | ||
239 | { | ||
240 | struct usb_xpad *xpad = urb->context; | ||
241 | int retval; | ||
242 | |||
243 | switch (urb->status) { | ||
244 | case 0: | ||
245 | /* success */ | ||
246 | break; | ||
247 | case -ECONNRESET: | ||
248 | case -ENOENT: | ||
249 | case -ESHUTDOWN: | ||
250 | /* this urb is terminated, clean up */ | ||
251 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
252 | return; | ||
253 | default: | ||
254 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
255 | goto exit; | ||
256 | } | ||
257 | |||
258 | xpad_process_packet(xpad, 0, xpad->idata); | ||
259 | |||
260 | exit: | ||
261 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
262 | if (retval) | ||
263 | err ("%s - usb_submit_urb failed with result %d", | ||
264 | __FUNCTION__, retval); | ||
265 | } | ||
266 | |||
267 | static int xpad_open (struct input_dev *dev) | ||
268 | { | ||
269 | struct usb_xpad *xpad = input_get_drvdata(dev); | ||
270 | |||
271 | xpad->irq_in->dev = xpad->udev; | ||
272 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) | ||
273 | return -EIO; | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static void xpad_close (struct input_dev *dev) | ||
279 | { | ||
280 | struct usb_xpad *xpad = input_get_drvdata(dev); | ||
281 | |||
282 | usb_kill_urb(xpad->irq_in); | ||
283 | } | ||
284 | |||
285 | static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) | ||
286 | { | ||
287 | set_bit(abs, input_dev->absbit); | ||
288 | |||
289 | switch (abs) { | ||
290 | case ABS_X: | ||
291 | case ABS_Y: | ||
292 | case ABS_RX: | ||
293 | case ABS_RY: /* the two sticks */ | ||
294 | input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128); | ||
295 | break; | ||
296 | case ABS_Z: | ||
297 | case ABS_RZ: /* the triggers */ | ||
298 | input_set_abs_params(input_dev, abs, 0, 255, 0, 0); | ||
299 | break; | ||
300 | case ABS_HAT0X: | ||
301 | case ABS_HAT0Y: /* the d-pad (only if MAP_DPAD_TO_AXES) */ | ||
302 | input_set_abs_params(input_dev, abs, -1, 1, 0, 0); | ||
303 | break; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
308 | { | ||
309 | struct usb_device *udev = interface_to_usbdev (intf); | ||
310 | struct usb_xpad *xpad; | ||
311 | struct input_dev *input_dev; | ||
312 | struct usb_endpoint_descriptor *ep_irq_in; | ||
313 | int i; | ||
314 | int error = -ENOMEM; | ||
315 | |||
316 | for (i = 0; xpad_device[i].idVendor; i++) { | ||
317 | if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && | ||
318 | (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) | ||
319 | break; | ||
320 | } | ||
321 | |||
322 | xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); | ||
323 | input_dev = input_allocate_device(); | ||
324 | if (!xpad || !input_dev) | ||
325 | goto fail1; | ||
326 | |||
327 | xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, | ||
328 | GFP_ATOMIC, &xpad->idata_dma); | ||
329 | if (!xpad->idata) | ||
330 | goto fail1; | ||
331 | |||
332 | xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); | ||
333 | if (!xpad->irq_in) | ||
334 | goto fail2; | ||
335 | |||
336 | xpad->udev = udev; | ||
337 | xpad->dpad_mapping = xpad_device[i].dpad_mapping; | ||
338 | if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) | ||
339 | xpad->dpad_mapping = dpad_to_buttons; | ||
340 | xpad->dev = input_dev; | ||
341 | usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); | ||
342 | strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); | ||
343 | |||
344 | input_dev->name = xpad_device[i].name; | ||
345 | input_dev->phys = xpad->phys; | ||
346 | usb_to_input_id(udev, &input_dev->id); | ||
347 | input_dev->dev.parent = &intf->dev; | ||
348 | |||
349 | input_set_drvdata(input_dev, xpad); | ||
350 | |||
351 | input_dev->open = xpad_open; | ||
352 | input_dev->close = xpad_close; | ||
353 | |||
354 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
355 | |||
356 | /* set up buttons */ | ||
357 | for (i = 0; xpad_btn[i] >= 0; i++) | ||
358 | set_bit(xpad_btn[i], input_dev->keybit); | ||
359 | if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) | ||
360 | for (i = 0; xpad_btn_pad[i] >= 0; i++) | ||
361 | set_bit(xpad_btn_pad[i], input_dev->keybit); | ||
362 | |||
363 | /* set up axes */ | ||
364 | for (i = 0; xpad_abs[i] >= 0; i++) | ||
365 | xpad_set_up_abs(input_dev, xpad_abs[i]); | ||
366 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) | ||
367 | for (i = 0; xpad_abs_pad[i] >= 0; i++) | ||
368 | xpad_set_up_abs(input_dev, xpad_abs_pad[i]); | ||
369 | |||
370 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; | ||
371 | usb_fill_int_urb(xpad->irq_in, udev, | ||
372 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), | ||
373 | xpad->idata, XPAD_PKT_LEN, xpad_irq_in, | ||
374 | xpad, ep_irq_in->bInterval); | ||
375 | xpad->irq_in->transfer_dma = xpad->idata_dma; | ||
376 | xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
377 | |||
378 | error = input_register_device(xpad->dev); | ||
379 | if (error) | ||
380 | goto fail3; | ||
381 | |||
382 | usb_set_intfdata(intf, xpad); | ||
383 | return 0; | ||
384 | |||
385 | fail3: usb_free_urb(xpad->irq_in); | ||
386 | fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); | ||
387 | fail1: input_free_device(input_dev); | ||
388 | kfree(xpad); | ||
389 | return error; | ||
390 | |||
391 | } | ||
392 | |||
393 | static void xpad_disconnect(struct usb_interface *intf) | ||
394 | { | ||
395 | struct usb_xpad *xpad = usb_get_intfdata (intf); | ||
396 | |||
397 | usb_set_intfdata(intf, NULL); | ||
398 | if (xpad) { | ||
399 | usb_kill_urb(xpad->irq_in); | ||
400 | input_unregister_device(xpad->dev); | ||
401 | usb_free_urb(xpad->irq_in); | ||
402 | usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, | ||
403 | xpad->idata, xpad->idata_dma); | ||
404 | kfree(xpad); | ||
405 | } | ||
406 | } | ||
407 | |||
408 | static struct usb_driver xpad_driver = { | ||
409 | .name = "xpad", | ||
410 | .probe = xpad_probe, | ||
411 | .disconnect = xpad_disconnect, | ||
412 | .id_table = xpad_table, | ||
413 | }; | ||
414 | |||
415 | static int __init usb_xpad_init(void) | ||
416 | { | ||
417 | int result = usb_register(&xpad_driver); | ||
418 | if (result == 0) | ||
419 | info(DRIVER_DESC ":" DRIVER_VERSION); | ||
420 | return result; | ||
421 | } | ||
422 | |||
423 | static void __exit usb_xpad_exit(void) | ||
424 | { | ||
425 | usb_deregister(&xpad_driver); | ||
426 | } | ||
427 | |||
428 | module_init(usb_xpad_init); | ||
429 | module_exit(usb_xpad_exit); | ||
430 | |||
431 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
432 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
433 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9f42e4d3649e..bd707b86c114 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -226,6 +226,7 @@ config KEYBOARD_PXA27x | |||
226 | config KEYBOARD_AAED2000 | 226 | config KEYBOARD_AAED2000 |
227 | tristate "AAED-2000 keyboard" | 227 | tristate "AAED-2000 keyboard" |
228 | depends on MACH_AAED2000 | 228 | depends on MACH_AAED2000 |
229 | select INPUT_POLLDEV | ||
229 | default y | 230 | default y |
230 | help | 231 | help |
231 | Say Y here to enable the keyboard on the Agilent AAED-2000 | 232 | Say Y here to enable the keyboard on the Agilent AAED-2000 |
diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c index 3a37505f067c..63d6ead6b877 100644 --- a/drivers/input/keyboard/aaed2000_kbd.c +++ b/drivers/input/keyboard/aaed2000_kbd.c | |||
@@ -14,12 +14,11 @@ | |||
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/input.h> | 17 | #include <linux/input-polldev.h> |
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/workqueue.h> | ||
23 | 22 | ||
24 | #include <asm/arch/hardware.h> | 23 | #include <asm/arch/hardware.h> |
25 | #include <asm/arch/aaed2000.h> | 24 | #include <asm/arch/aaed2000.h> |
@@ -46,8 +45,7 @@ static unsigned char aaedkbd_keycode[NR_SCANCODES] = { | |||
46 | 45 | ||
47 | struct aaedkbd { | 46 | struct aaedkbd { |
48 | unsigned char keycode[ARRAY_SIZE(aaedkbd_keycode)]; | 47 | unsigned char keycode[ARRAY_SIZE(aaedkbd_keycode)]; |
49 | struct input_dev *input; | 48 | struct input_polled_dev *poll_dev; |
50 | struct work_struct workq; | ||
51 | int kbdscan_state[KB_COLS]; | 49 | int kbdscan_state[KB_COLS]; |
52 | int kbdscan_count[KB_COLS]; | 50 | int kbdscan_count[KB_COLS]; |
53 | }; | 51 | }; |
@@ -64,14 +62,15 @@ static void aaedkbd_report_col(struct aaedkbd *aaedkbd, | |||
64 | scancode = SCANCODE(row, col); | 62 | scancode = SCANCODE(row, col); |
65 | pressed = rowd & KB_ROWMASK(row); | 63 | pressed = rowd & KB_ROWMASK(row); |
66 | 64 | ||
67 | input_report_key(aaedkbd->input, aaedkbd->keycode[scancode], pressed); | 65 | input_report_key(aaedkbd->poll_dev->input, |
66 | aaedkbd->keycode[scancode], pressed); | ||
68 | } | 67 | } |
69 | } | 68 | } |
70 | 69 | ||
71 | /* Scan the hardware keyboard and push any changes up through the input layer */ | 70 | /* Scan the hardware keyboard and push any changes up through the input layer */ |
72 | static void aaedkbd_work(void *data) | 71 | static void aaedkbd_poll(struct input_polled_dev *dev) |
73 | { | 72 | { |
74 | struct aaedkbd *aaedkbd = data; | 73 | struct aaedkbd *aaedkbd = dev->private; |
75 | unsigned int col, rowd; | 74 | unsigned int col, rowd; |
76 | 75 | ||
77 | col = 0; | 76 | col = 0; |
@@ -90,51 +89,34 @@ static void aaedkbd_work(void *data) | |||
90 | } while (col < KB_COLS); | 89 | } while (col < KB_COLS); |
91 | 90 | ||
92 | AAEC_GPIO_KSCAN = 0x07; | 91 | AAEC_GPIO_KSCAN = 0x07; |
93 | input_sync(aaedkbd->input); | 92 | input_sync(dev->input); |
94 | |||
95 | schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL)); | ||
96 | } | ||
97 | |||
98 | static int aaedkbd_open(struct input_dev *indev) | ||
99 | { | ||
100 | struct aaedkbd *aaedkbd = input_get_drvdata(indev); | ||
101 | |||
102 | schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL)); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static void aaedkbd_close(struct input_dev *indev) | ||
108 | { | ||
109 | struct aaedkbd *aaedkbd = input_get_drvdata(indev); | ||
110 | |||
111 | cancel_delayed_work(&aaedkbd->workq); | ||
112 | flush_scheduled_work(); | ||
113 | } | 93 | } |
114 | 94 | ||
115 | static int __devinit aaedkbd_probe(struct platform_device *pdev) | 95 | static int __devinit aaedkbd_probe(struct platform_device *pdev) |
116 | { | 96 | { |
117 | struct aaedkbd *aaedkbd; | 97 | struct aaedkbd *aaedkbd; |
98 | struct input_polled_dev *poll_dev; | ||
118 | struct input_dev *input_dev; | 99 | struct input_dev *input_dev; |
119 | int i; | 100 | int i; |
120 | int error; | 101 | int error; |
121 | 102 | ||
122 | aaedkbd = kzalloc(sizeof(struct aaedkbd), GFP_KERNEL); | 103 | aaedkbd = kzalloc(sizeof(struct aaedkbd), GFP_KERNEL); |
123 | input_dev = input_allocate_device(); | 104 | poll_dev = input_allocate_polled_device(); |
124 | if (!aaedkbd || !input_dev) { | 105 | if (!aaedkbd || !poll_dev) { |
125 | error = -ENOMEM; | 106 | error = -ENOMEM; |
126 | goto fail; | 107 | goto fail; |
127 | } | 108 | } |
128 | 109 | ||
129 | platform_set_drvdata(pdev, aaedkbd); | 110 | platform_set_drvdata(pdev, aaedkbd); |
130 | 111 | ||
131 | aaedkbd->input = input_dev; | 112 | aaedkbd->poll_dev = poll_dev; |
132 | |||
133 | /* Init keyboard rescan workqueue */ | ||
134 | INIT_WORK(&aaedkbd->workq, aaedkbd_work, aaedkbd); | ||
135 | |||
136 | memcpy(aaedkbd->keycode, aaedkbd_keycode, sizeof(aaedkbd->keycode)); | 113 | memcpy(aaedkbd->keycode, aaedkbd_keycode, sizeof(aaedkbd->keycode)); |
137 | 114 | ||
115 | poll_dev->private = aaedkbd; | ||
116 | poll_dev->poll = aaedkbd_poll; | ||
117 | poll_dev->poll_interval = SCAN_INTERVAL; | ||
118 | |||
119 | input_dev = poll_dev->input; | ||
138 | input_dev->name = "AAED-2000 Keyboard"; | 120 | input_dev->name = "AAED-2000 Keyboard"; |
139 | input_dev->phys = "aaedkbd/input0"; | 121 | input_dev->phys = "aaedkbd/input0"; |
140 | input_dev->id.bustype = BUS_HOST; | 122 | input_dev->id.bustype = BUS_HOST; |
@@ -143,8 +125,6 @@ static int __devinit aaedkbd_probe(struct platform_device *pdev) | |||
143 | input_dev->id.version = 0x0100; | 125 | input_dev->id.version = 0x0100; |
144 | input_dev->dev.parent = &pdev->dev; | 126 | input_dev->dev.parent = &pdev->dev; |
145 | 127 | ||
146 | input_set_drvdata(input_dev, aaedkbd); | ||
147 | |||
148 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | 128 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); |
149 | input_dev->keycode = aaedkbd->keycode; | 129 | input_dev->keycode = aaedkbd->keycode; |
150 | input_dev->keycodesize = sizeof(unsigned char); | 130 | input_dev->keycodesize = sizeof(unsigned char); |
@@ -154,17 +134,14 @@ static int __devinit aaedkbd_probe(struct platform_device *pdev) | |||
154 | set_bit(aaedkbd->keycode[i], input_dev->keybit); | 134 | set_bit(aaedkbd->keycode[i], input_dev->keybit); |
155 | clear_bit(0, input_dev->keybit); | 135 | clear_bit(0, input_dev->keybit); |
156 | 136 | ||
157 | input_dev->open = aaedkbd_open; | 137 | error = input_register_polled_device(aaedkbd->poll_dev); |
158 | input_dev->close = aaedkbd_close; | ||
159 | |||
160 | error = input_register_device(aaedkbd->input); | ||
161 | if (error) | 138 | if (error) |
162 | goto fail; | 139 | goto fail; |
163 | 140 | ||
164 | return 0; | 141 | return 0; |
165 | 142 | ||
166 | fail: kfree(aaedkbd); | 143 | fail: kfree(aaedkbd); |
167 | input_free_device(input_dev); | 144 | input_free_polled_device(poll_dev); |
168 | return error; | 145 | return error; |
169 | } | 146 | } |
170 | 147 | ||
@@ -172,7 +149,8 @@ static int __devexit aaedkbd_remove(struct platform_device *pdev) | |||
172 | { | 149 | { |
173 | struct aaedkbd *aaedkbd = platform_get_drvdata(pdev); | 150 | struct aaedkbd *aaedkbd = platform_get_drvdata(pdev); |
174 | 151 | ||
175 | input_unregister_device(aaedkbd->input); | 152 | input_unregister_polled_device(aaedkbd->poll_dev); |
153 | input_free_polled_device(aaedkbd->poll_dev); | ||
176 | kfree(aaedkbd); | 154 | kfree(aaedkbd); |
177 | 155 | ||
178 | return 0; | 156 | return 0; |
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 1d0d3e765db6..6013ace94d98 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -40,6 +40,18 @@ config INPUT_M68K_BEEP | |||
40 | tristate "M68k Beeper support" | 40 | tristate "M68k Beeper support" |
41 | depends on M68K | 41 | depends on M68K |
42 | 42 | ||
43 | config INPUT_IXP4XX_BEEPER | ||
44 | tristate "IXP4XX Beeper support" | ||
45 | depends on ARCH_IXP4XX | ||
46 | help | ||
47 | If you say yes here, you can connect a beeper to the | ||
48 | ixp4xx gpio pins. This is used by the LinkSys NSLU2. | ||
49 | |||
50 | If unsure, say Y. | ||
51 | |||
52 | To compile this driver as a module, choose M here: the | ||
53 | module will be called ixp4xx-beeper. | ||
54 | |||
43 | config INPUT_COBALT_BTNS | 55 | config INPUT_COBALT_BTNS |
44 | tristate "Cobalt button interface" | 56 | tristate "Cobalt button interface" |
45 | depends on MIPS_COBALT | 57 | depends on MIPS_COBALT |
@@ -70,17 +82,79 @@ config INPUT_ATLAS_BTNS | |||
70 | To compile this driver as a module, choose M here: the module will | 82 | To compile this driver as a module, choose M here: the module will |
71 | be called atlas_btns. | 83 | be called atlas_btns. |
72 | 84 | ||
73 | config INPUT_IXP4XX_BEEPER | 85 | config INPUT_ATI_REMOTE |
74 | tristate "IXP4XX Beeper support" | 86 | tristate "ATI / X10 USB RF remote control" |
75 | depends on ARCH_IXP4XX | 87 | select USB |
76 | help | 88 | help |
77 | If you say yes here, you can connect a beeper to the | 89 | Say Y here if you want to use an ATI or X10 "Lola" USB remote control. |
78 | ixp4xx gpio pins. This is used by the LinkSys NSLU2. | 90 | These are RF remotes with USB receivers. |
91 | The ATI remote comes with many of ATI's All-In-Wonder video cards. | ||
92 | The X10 "Lola" remote is available at: | ||
93 | <http://www.x10.com/products/lola_sg1.htm> | ||
94 | This driver provides mouse pointer, left and right mouse buttons, | ||
95 | and maps all the other remote buttons to keypress events. | ||
96 | |||
97 | To compile this driver as a module, choose M here: the module will be | ||
98 | called ati_remote. | ||
99 | |||
100 | config INPUT_ATI_REMOTE2 | ||
101 | tristate "ATI / Philips USB RF remote control" | ||
102 | select USB | ||
103 | help | ||
104 | Say Y here if you want to use an ATI or Philips USB RF remote control. | ||
105 | These are RF remotes with USB receivers. | ||
106 | ATI Remote Wonder II comes with some ATI's All-In-Wonder video cards | ||
107 | and is also available as a separate product. | ||
108 | This driver provides mouse pointer, left and right mouse buttons, | ||
109 | and maps all the other remote buttons to keypress events. | ||
110 | |||
111 | To compile this driver as a module, choose M here: the module will be | ||
112 | called ati_remote2. | ||
113 | |||
114 | config INPUT_KEYSPAN_REMOTE | ||
115 | tristate "Keyspan DMR USB remote control (EXPERIMENTAL)" | ||
116 | depends on EXPERIMENTAL | ||
117 | select USB | ||
118 | help | ||
119 | Say Y here if you want to use a Keyspan DMR USB remote control. | ||
120 | Currently only the UIA-11 type of receiver has been tested. The tag | ||
121 | on the receiver that connects to the USB port should have a P/N that | ||
122 | will tell you what type of DMR you have. The UIA-10 type is not | ||
123 | supported at this time. This driver maps all buttons to keypress | ||
124 | events. | ||
79 | 125 | ||
80 | If unsure, say Y. | 126 | To compile this driver as a module, choose M here: the module will |
127 | be called keyspan_remote. | ||
128 | |||
129 | config INPUT_POWERMATE | ||
130 | tristate "Griffin PowerMate and Contour Jog support" | ||
131 | select USB | ||
132 | help | ||
133 | Say Y here if you want to use Griffin PowerMate or Contour Jog devices. | ||
134 | These are aluminum dials which can measure clockwise and anticlockwise | ||
135 | rotation. The dial also acts as a pushbutton. The base contains an LED | ||
136 | which can be instructed to pulse or to switch to a particular intensity. | ||
137 | |||
138 | You can download userspace tools from | ||
139 | <http://sowerbutts.com/powermate/>. | ||
81 | 140 | ||
82 | To compile this driver as a module, choose M here: the | 141 | To compile this driver as a module, choose M here: the |
83 | module will be called ixp4xx-beeper. | 142 | module will be called powermate. |
143 | |||
144 | config INPUT_YEALINK | ||
145 | tristate "Yealink usb-p1k voip phone" | ||
146 | depends EXPERIMENTAL | ||
147 | select USB | ||
148 | help | ||
149 | Say Y here if you want to enable keyboard and LCD functions of the | ||
150 | Yealink usb-p1k usb phones. The audio part is enabled by the generic | ||
151 | usb sound driver, so you might want to enable that as well. | ||
152 | |||
153 | For information about how to use these additional functions, see | ||
154 | <file:Documentation/input/yealink.txt>. | ||
155 | |||
156 | To compile this driver as a module, choose M here: the module will be | ||
157 | called yealink. | ||
84 | 158 | ||
85 | config INPUT_UINPUT | 159 | config INPUT_UINPUT |
86 | tristate "User level driver support" | 160 | tristate "User level driver support" |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 21e3cca0d33e..8b2f7799e25c 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -8,9 +8,14 @@ obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o | |||
8 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o | 8 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o |
9 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o | 9 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o |
10 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o | 10 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o |
11 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | 11 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o |
12 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o | 12 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o |
13 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o | 13 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o |
14 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | 14 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
15 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o | ||
16 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | ||
17 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o | ||
18 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o | ||
19 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o | ||
15 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | 20 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o |
16 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o | 21 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o |
diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c new file mode 100644 index 000000000000..471aab206443 --- /dev/null +++ b/drivers/input/misc/ati_remote.c | |||
@@ -0,0 +1,862 @@ | |||
1 | /* | ||
2 | * USB ATI Remote support | ||
3 | * | ||
4 | * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> | ||
5 | * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev | ||
6 | * | ||
7 | * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including | ||
8 | * porting to the 2.6 kernel interfaces, along with other modification | ||
9 | * to better match the style of the existing usb/input drivers. However, the | ||
10 | * protocol and hardware handling is essentially unchanged from 2.1.1. | ||
11 | * | ||
12 | * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by | ||
13 | * Vojtech Pavlik. | ||
14 | * | ||
15 | * Changes: | ||
16 | * | ||
17 | * Feb 2004: Torrey Hoffman <thoffman@arnor.net> | ||
18 | * Version 2.2.0 | ||
19 | * Jun 2004: Torrey Hoffman <thoffman@arnor.net> | ||
20 | * Version 2.2.1 | ||
21 | * Added key repeat support contributed by: | ||
22 | * Vincent Vanackere <vanackere@lif.univ-mrs.fr> | ||
23 | * Added support for the "Lola" remote contributed by: | ||
24 | * Seth Cohn <sethcohn@yahoo.com> | ||
25 | * | ||
26 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | ||
27 | * | ||
28 | * This program is free software; you can redistribute it and/or modify | ||
29 | * it under the terms of the GNU General Public License as published by | ||
30 | * the Free Software Foundation; either version 2 of the License, or | ||
31 | * (at your option) any later version. | ||
32 | * | ||
33 | * This program is distributed in the hope that it will be useful, | ||
34 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
35 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
36 | * GNU General Public License for more details. | ||
37 | * | ||
38 | * You should have received a copy of the GNU General Public License | ||
39 | * along with this program; if not, write to the Free Software | ||
40 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
41 | * | ||
42 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | ||
43 | * | ||
44 | * Hardware & software notes | ||
45 | * | ||
46 | * These remote controls are distributed by ATI as part of their | ||
47 | * "All-In-Wonder" video card packages. The receiver self-identifies as a | ||
48 | * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". | ||
49 | * | ||
50 | * The "Lola" remote is available from X10. See: | ||
51 | * http://www.x10.com/products/lola_sg1.htm | ||
52 | * The Lola is similar to the ATI remote but has no mouse support, and slightly | ||
53 | * different keys. | ||
54 | * | ||
55 | * It is possible to use multiple receivers and remotes on multiple computers | ||
56 | * simultaneously by configuring them to use specific channels. | ||
57 | * | ||
58 | * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. | ||
59 | * Actually, it may even support more, at least in some revisions of the | ||
60 | * hardware. | ||
61 | * | ||
62 | * Each remote can be configured to transmit on one channel as follows: | ||
63 | * - Press and hold the "hand icon" button. | ||
64 | * - When the red LED starts to blink, let go of the "hand icon" button. | ||
65 | * - When it stops blinking, input the channel code as two digits, from 01 | ||
66 | * to 16, and press the hand icon again. | ||
67 | * | ||
68 | * The timing can be a little tricky. Try loading the module with debug=1 | ||
69 | * to have the kernel print out messages about the remote control number | ||
70 | * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. | ||
71 | * | ||
72 | * The driver has a "channel_mask" parameter. This bitmask specifies which | ||
73 | * channels will be ignored by the module. To mask out channels, just add | ||
74 | * all the 2^channel_number values together. | ||
75 | * | ||
76 | * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote | ||
77 | * ignore signals coming from remote controls transmitting on channel 4, but | ||
78 | * accept all other channels. | ||
79 | * | ||
80 | * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be | ||
81 | * ignored. | ||
82 | * | ||
83 | * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this | ||
84 | * parameter are unused. | ||
85 | * | ||
86 | */ | ||
87 | |||
88 | #include <linux/kernel.h> | ||
89 | #include <linux/errno.h> | ||
90 | #include <linux/init.h> | ||
91 | #include <linux/slab.h> | ||
92 | #include <linux/module.h> | ||
93 | #include <linux/moduleparam.h> | ||
94 | #include <linux/usb/input.h> | ||
95 | #include <linux/wait.h> | ||
96 | #include <linux/jiffies.h> | ||
97 | |||
98 | /* | ||
99 | * Module and Version Information, Module Parameters | ||
100 | */ | ||
101 | |||
102 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 | ||
103 | #define ATI_REMOTE_PRODUCT_ID 0x004 | ||
104 | #define LOLA_REMOTE_PRODUCT_ID 0x002 | ||
105 | #define MEDION_REMOTE_PRODUCT_ID 0x006 | ||
106 | |||
107 | #define DRIVER_VERSION "2.2.1" | ||
108 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" | ||
109 | #define DRIVER_DESC "ATI/X10 RF USB Remote Control" | ||
110 | |||
111 | #define NAME_BUFSIZE 80 /* size of product name, path buffers */ | ||
112 | #define DATA_BUFSIZE 63 /* size of URB data buffers */ | ||
113 | |||
114 | /* | ||
115 | * Duplicate event filtering time. | ||
116 | * Sequential, identical KIND_FILTERED inputs with less than | ||
117 | * FILTER_TIME milliseconds between them are considered as repeat | ||
118 | * events. The hardware generates 5 events for the first keypress | ||
119 | * and we have to take this into account for an accurate repeat | ||
120 | * behaviour. | ||
121 | */ | ||
122 | #define FILTER_TIME 60 /* msec */ | ||
123 | #define REPEAT_DELAY 500 /* msec */ | ||
124 | |||
125 | static unsigned long channel_mask; | ||
126 | module_param(channel_mask, ulong, 0644); | ||
127 | MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); | ||
128 | |||
129 | static int debug; | ||
130 | module_param(debug, int, 0644); | ||
131 | MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); | ||
132 | |||
133 | static int repeat_filter = FILTER_TIME; | ||
134 | module_param(repeat_filter, int, 0644); | ||
135 | MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec"); | ||
136 | |||
137 | static int repeat_delay = REPEAT_DELAY; | ||
138 | module_param(repeat_delay, int, 0644); | ||
139 | MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec"); | ||
140 | |||
141 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) | ||
142 | #undef err | ||
143 | #define err(format, arg...) printk(KERN_ERR format , ## arg) | ||
144 | |||
145 | static struct usb_device_id ati_remote_table[] = { | ||
146 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, | ||
147 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, | ||
148 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) }, | ||
149 | {} /* Terminating entry */ | ||
150 | }; | ||
151 | |||
152 | MODULE_DEVICE_TABLE(usb, ati_remote_table); | ||
153 | |||
154 | /* Get hi and low bytes of a 16-bits int */ | ||
155 | #define HI(a) ((unsigned char)((a) >> 8)) | ||
156 | #define LO(a) ((unsigned char)((a) & 0xff)) | ||
157 | |||
158 | #define SEND_FLAG_IN_PROGRESS 1 | ||
159 | #define SEND_FLAG_COMPLETE 2 | ||
160 | |||
161 | /* Device initialization strings */ | ||
162 | static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; | ||
163 | static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; | ||
164 | |||
165 | struct ati_remote { | ||
166 | struct input_dev *idev; | ||
167 | struct usb_device *udev; | ||
168 | struct usb_interface *interface; | ||
169 | |||
170 | struct urb *irq_urb; | ||
171 | struct urb *out_urb; | ||
172 | struct usb_endpoint_descriptor *endpoint_in; | ||
173 | struct usb_endpoint_descriptor *endpoint_out; | ||
174 | unsigned char *inbuf; | ||
175 | unsigned char *outbuf; | ||
176 | dma_addr_t inbuf_dma; | ||
177 | dma_addr_t outbuf_dma; | ||
178 | |||
179 | unsigned char old_data[2]; /* Detect duplicate events */ | ||
180 | unsigned long old_jiffies; | ||
181 | unsigned long acc_jiffies; /* handle acceleration */ | ||
182 | unsigned long first_jiffies; | ||
183 | |||
184 | unsigned int repeat_count; | ||
185 | |||
186 | char name[NAME_BUFSIZE]; | ||
187 | char phys[NAME_BUFSIZE]; | ||
188 | |||
189 | wait_queue_head_t wait; | ||
190 | int send_flags; | ||
191 | }; | ||
192 | |||
193 | /* "Kinds" of messages sent from the hardware to the driver. */ | ||
194 | #define KIND_END 0 | ||
195 | #define KIND_LITERAL 1 /* Simply pass to input system */ | ||
196 | #define KIND_FILTERED 2 /* Add artificial key-up events, drop keyrepeats */ | ||
197 | #define KIND_LU 3 /* Directional keypad diagonals - left up, */ | ||
198 | #define KIND_RU 4 /* right up, */ | ||
199 | #define KIND_LD 5 /* left down, */ | ||
200 | #define KIND_RD 6 /* right down */ | ||
201 | #define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/ | ||
202 | |||
203 | /* Translation table from hardware messages to input events. */ | ||
204 | static const struct { | ||
205 | short kind; | ||
206 | unsigned char data1, data2; | ||
207 | int type; | ||
208 | unsigned int code; | ||
209 | int value; | ||
210 | } ati_remote_tbl[] = { | ||
211 | /* Directional control pad axes */ | ||
212 | {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ | ||
213 | {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ | ||
214 | {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ | ||
215 | {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ | ||
216 | /* Directional control pad diagonals */ | ||
217 | {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ | ||
218 | {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ | ||
219 | {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ | ||
220 | {KIND_RD, 0x3b, 0x76, EV_REL, 0, 0}, /* right down */ | ||
221 | |||
222 | /* "Mouse button" buttons */ | ||
223 | {KIND_LITERAL, 0x3d, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */ | ||
224 | {KIND_LITERAL, 0x3e, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */ | ||
225 | {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ | ||
226 | {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ | ||
227 | |||
228 | /* Artificial "doubleclick" events are generated by the hardware. | ||
229 | * They are mapped to the "side" and "extra" mouse buttons here. */ | ||
230 | {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ | ||
231 | {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ | ||
232 | |||
233 | /* keyboard. */ | ||
234 | {KIND_FILTERED, 0xd2, 0x0d, EV_KEY, KEY_1, 1}, | ||
235 | {KIND_FILTERED, 0xd3, 0x0e, EV_KEY, KEY_2, 1}, | ||
236 | {KIND_FILTERED, 0xd4, 0x0f, EV_KEY, KEY_3, 1}, | ||
237 | {KIND_FILTERED, 0xd5, 0x10, EV_KEY, KEY_4, 1}, | ||
238 | {KIND_FILTERED, 0xd6, 0x11, EV_KEY, KEY_5, 1}, | ||
239 | {KIND_FILTERED, 0xd7, 0x12, EV_KEY, KEY_6, 1}, | ||
240 | {KIND_FILTERED, 0xd8, 0x13, EV_KEY, KEY_7, 1}, | ||
241 | {KIND_FILTERED, 0xd9, 0x14, EV_KEY, KEY_8, 1}, | ||
242 | {KIND_FILTERED, 0xda, 0x15, EV_KEY, KEY_9, 1}, | ||
243 | {KIND_FILTERED, 0xdc, 0x17, EV_KEY, KEY_0, 1}, | ||
244 | {KIND_FILTERED, 0xc5, 0x00, EV_KEY, KEY_A, 1}, | ||
245 | {KIND_FILTERED, 0xc6, 0x01, EV_KEY, KEY_B, 1}, | ||
246 | {KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_C, 1}, | ||
247 | {KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_D, 1}, | ||
248 | {KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_E, 1}, | ||
249 | {KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_F, 1}, | ||
250 | |||
251 | /* "special" keys */ | ||
252 | {KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1}, /* "check" */ | ||
253 | {KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1}, /* "menu" */ | ||
254 | {KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1}, /* Power */ | ||
255 | {KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_TV, 1}, /* TV */ | ||
256 | {KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1}, /* DVD */ | ||
257 | {KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1}, /* WEB */ | ||
258 | {KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1}, /* "book" */ | ||
259 | {KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1}, /* "hand" */ | ||
260 | {KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_COFFEE, 1}, /* "timer" */ | ||
261 | {KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_FRONT, 1}, /* "max" */ | ||
262 | {KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1}, /* left */ | ||
263 | {KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1}, /* right */ | ||
264 | {KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1}, /* down */ | ||
265 | {KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1}, /* up */ | ||
266 | {KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1}, /* "OK" */ | ||
267 | {KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */ | ||
268 | {KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1}, /* VOL - */ | ||
269 | {KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1}, /* MUTE */ | ||
270 | {KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1}, /* CH + */ | ||
271 | {KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */ | ||
272 | {KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1}, /* ( o) red */ | ||
273 | {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ | ||
274 | {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ | ||
275 | {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ | ||
276 | {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ | ||
277 | {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ | ||
278 | {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ | ||
279 | {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ | ||
280 | {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ | ||
281 | {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ | ||
282 | {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ | ||
283 | {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ | ||
284 | |||
285 | {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} | ||
286 | }; | ||
287 | |||
288 | /* Local function prototypes */ | ||
289 | static void ati_remote_dump (unsigned char *data, unsigned int actual_length); | ||
290 | static int ati_remote_open (struct input_dev *inputdev); | ||
291 | static void ati_remote_close (struct input_dev *inputdev); | ||
292 | static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data); | ||
293 | static void ati_remote_irq_out (struct urb *urb); | ||
294 | static void ati_remote_irq_in (struct urb *urb); | ||
295 | static void ati_remote_input_report (struct urb *urb); | ||
296 | static int ati_remote_initialize (struct ati_remote *ati_remote); | ||
297 | static int ati_remote_probe (struct usb_interface *interface, const struct usb_device_id *id); | ||
298 | static void ati_remote_disconnect (struct usb_interface *interface); | ||
299 | |||
300 | /* usb specific object to register with the usb subsystem */ | ||
301 | static struct usb_driver ati_remote_driver = { | ||
302 | .name = "ati_remote", | ||
303 | .probe = ati_remote_probe, | ||
304 | .disconnect = ati_remote_disconnect, | ||
305 | .id_table = ati_remote_table, | ||
306 | }; | ||
307 | |||
308 | /* | ||
309 | * ati_remote_dump_input | ||
310 | */ | ||
311 | static void ati_remote_dump(unsigned char *data, unsigned int len) | ||
312 | { | ||
313 | if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) | ||
314 | warn("Weird byte 0x%02x", data[0]); | ||
315 | else if (len == 4) | ||
316 | warn("Weird key %02x %02x %02x %02x", | ||
317 | data[0], data[1], data[2], data[3]); | ||
318 | else | ||
319 | warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...", | ||
320 | len, data[0], data[1], data[2], data[3], data[4], data[5]); | ||
321 | } | ||
322 | |||
323 | /* | ||
324 | * ati_remote_open | ||
325 | */ | ||
326 | static int ati_remote_open(struct input_dev *inputdev) | ||
327 | { | ||
328 | struct ati_remote *ati_remote = input_get_drvdata(inputdev); | ||
329 | |||
330 | /* On first open, submit the read urb which was set up previously. */ | ||
331 | ati_remote->irq_urb->dev = ati_remote->udev; | ||
332 | if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { | ||
333 | dev_err(&ati_remote->interface->dev, | ||
334 | "%s: usb_submit_urb failed!\n", __FUNCTION__); | ||
335 | return -EIO; | ||
336 | } | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | /* | ||
342 | * ati_remote_close | ||
343 | */ | ||
344 | static void ati_remote_close(struct input_dev *inputdev) | ||
345 | { | ||
346 | struct ati_remote *ati_remote = input_get_drvdata(inputdev); | ||
347 | |||
348 | usb_kill_urb(ati_remote->irq_urb); | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * ati_remote_irq_out | ||
353 | */ | ||
354 | static void ati_remote_irq_out(struct urb *urb) | ||
355 | { | ||
356 | struct ati_remote *ati_remote = urb->context; | ||
357 | |||
358 | if (urb->status) { | ||
359 | dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", | ||
360 | __FUNCTION__, urb->status); | ||
361 | return; | ||
362 | } | ||
363 | |||
364 | ati_remote->send_flags |= SEND_FLAG_COMPLETE; | ||
365 | wmb(); | ||
366 | wake_up(&ati_remote->wait); | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * ati_remote_sendpacket | ||
371 | * | ||
372 | * Used to send device initialization strings | ||
373 | */ | ||
374 | static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) | ||
375 | { | ||
376 | int retval = 0; | ||
377 | |||
378 | /* Set up out_urb */ | ||
379 | memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); | ||
380 | ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); | ||
381 | |||
382 | ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; | ||
383 | ati_remote->out_urb->dev = ati_remote->udev; | ||
384 | ati_remote->send_flags = SEND_FLAG_IN_PROGRESS; | ||
385 | |||
386 | retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC); | ||
387 | if (retval) { | ||
388 | dev_dbg(&ati_remote->interface->dev, | ||
389 | "sendpacket: usb_submit_urb failed: %d\n", retval); | ||
390 | return retval; | ||
391 | } | ||
392 | |||
393 | wait_event_timeout(ati_remote->wait, | ||
394 | ((ati_remote->out_urb->status != -EINPROGRESS) || | ||
395 | (ati_remote->send_flags & SEND_FLAG_COMPLETE)), | ||
396 | HZ); | ||
397 | usb_kill_urb(ati_remote->out_urb); | ||
398 | |||
399 | return retval; | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * ati_remote_event_lookup | ||
404 | */ | ||
405 | static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) | ||
406 | { | ||
407 | int i; | ||
408 | |||
409 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { | ||
410 | /* | ||
411 | * Decide if the table entry matches the remote input. | ||
412 | */ | ||
413 | if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && | ||
414 | ((((ati_remote_tbl[i].data1 >> 4) - | ||
415 | (d1 >> 4) + rem) & 0x0f) == 0x0f) && | ||
416 | (ati_remote_tbl[i].data2 == d2)) | ||
417 | return i; | ||
418 | |||
419 | } | ||
420 | return -1; | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * ati_remote_compute_accel | ||
425 | * | ||
426 | * Implements acceleration curve for directional control pad | ||
427 | * If elapsed time since last event is > 1/4 second, user "stopped", | ||
428 | * so reset acceleration. Otherwise, user is probably holding the control | ||
429 | * pad down, so we increase acceleration, ramping up over two seconds to | ||
430 | * a maximum speed. | ||
431 | */ | ||
432 | static int ati_remote_compute_accel(struct ati_remote *ati_remote) | ||
433 | { | ||
434 | static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; | ||
435 | unsigned long now = jiffies; | ||
436 | int acc; | ||
437 | |||
438 | if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) { | ||
439 | acc = 1; | ||
440 | ati_remote->acc_jiffies = now; | ||
441 | } | ||
442 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125))) | ||
443 | acc = accel[0]; | ||
444 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250))) | ||
445 | acc = accel[1]; | ||
446 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500))) | ||
447 | acc = accel[2]; | ||
448 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000))) | ||
449 | acc = accel[3]; | ||
450 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500))) | ||
451 | acc = accel[4]; | ||
452 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000))) | ||
453 | acc = accel[5]; | ||
454 | else | ||
455 | acc = accel[6]; | ||
456 | |||
457 | return acc; | ||
458 | } | ||
459 | |||
460 | /* | ||
461 | * ati_remote_report_input | ||
462 | */ | ||
463 | static void ati_remote_input_report(struct urb *urb) | ||
464 | { | ||
465 | struct ati_remote *ati_remote = urb->context; | ||
466 | unsigned char *data= ati_remote->inbuf; | ||
467 | struct input_dev *dev = ati_remote->idev; | ||
468 | int index, acc; | ||
469 | int remote_num; | ||
470 | |||
471 | /* Deal with strange looking inputs */ | ||
472 | if ( (urb->actual_length != 4) || (data[0] != 0x14) || | ||
473 | ((data[3] & 0x0f) != 0x00) ) { | ||
474 | ati_remote_dump(data, urb->actual_length); | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | /* Mask unwanted remote channels. */ | ||
479 | /* note: remote_num is 0-based, channel 1 on remote == 0 here */ | ||
480 | remote_num = (data[3] >> 4) & 0x0f; | ||
481 | if (channel_mask & (1 << (remote_num + 1))) { | ||
482 | dbginfo(&ati_remote->interface->dev, | ||
483 | "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", | ||
484 | remote_num, data[1], data[2], channel_mask); | ||
485 | return; | ||
486 | } | ||
487 | |||
488 | /* Look up event code index in translation table */ | ||
489 | index = ati_remote_event_lookup(remote_num, data[1], data[2]); | ||
490 | if (index < 0) { | ||
491 | dev_warn(&ati_remote->interface->dev, | ||
492 | "Unknown input from channel 0x%02x: data %02x,%02x\n", | ||
493 | remote_num, data[1], data[2]); | ||
494 | return; | ||
495 | } | ||
496 | dbginfo(&ati_remote->interface->dev, | ||
497 | "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", | ||
498 | remote_num, data[1], data[2], index, ati_remote_tbl[index].code); | ||
499 | |||
500 | if (ati_remote_tbl[index].kind == KIND_LITERAL) { | ||
501 | input_event(dev, ati_remote_tbl[index].type, | ||
502 | ati_remote_tbl[index].code, | ||
503 | ati_remote_tbl[index].value); | ||
504 | input_sync(dev); | ||
505 | |||
506 | ati_remote->old_jiffies = jiffies; | ||
507 | return; | ||
508 | } | ||
509 | |||
510 | if (ati_remote_tbl[index].kind == KIND_FILTERED) { | ||
511 | unsigned long now = jiffies; | ||
512 | |||
513 | /* Filter duplicate events which happen "too close" together. */ | ||
514 | if (ati_remote->old_data[0] == data[1] && | ||
515 | ati_remote->old_data[1] == data[2] && | ||
516 | time_before(now, ati_remote->old_jiffies + | ||
517 | msecs_to_jiffies(repeat_filter))) { | ||
518 | ati_remote->repeat_count++; | ||
519 | } else { | ||
520 | ati_remote->repeat_count = 0; | ||
521 | ati_remote->first_jiffies = now; | ||
522 | } | ||
523 | |||
524 | ati_remote->old_data[0] = data[1]; | ||
525 | ati_remote->old_data[1] = data[2]; | ||
526 | ati_remote->old_jiffies = now; | ||
527 | |||
528 | /* Ensure we skip at least the 4 first duplicate events (generated | ||
529 | * by a single keypress), and continue skipping until repeat_delay | ||
530 | * msecs have passed | ||
531 | */ | ||
532 | if (ati_remote->repeat_count > 0 && | ||
533 | (ati_remote->repeat_count < 5 || | ||
534 | time_before(now, ati_remote->first_jiffies + | ||
535 | msecs_to_jiffies(repeat_delay)))) | ||
536 | return; | ||
537 | |||
538 | |||
539 | input_event(dev, ati_remote_tbl[index].type, | ||
540 | ati_remote_tbl[index].code, 1); | ||
541 | input_sync(dev); | ||
542 | input_event(dev, ati_remote_tbl[index].type, | ||
543 | ati_remote_tbl[index].code, 0); | ||
544 | input_sync(dev); | ||
545 | |||
546 | } else { | ||
547 | |||
548 | /* | ||
549 | * Other event kinds are from the directional control pad, and have an | ||
550 | * acceleration factor applied to them. Without this acceleration, the | ||
551 | * control pad is mostly unusable. | ||
552 | */ | ||
553 | acc = ati_remote_compute_accel(ati_remote); | ||
554 | |||
555 | switch (ati_remote_tbl[index].kind) { | ||
556 | case KIND_ACCEL: | ||
557 | input_event(dev, ati_remote_tbl[index].type, | ||
558 | ati_remote_tbl[index].code, | ||
559 | ati_remote_tbl[index].value * acc); | ||
560 | break; | ||
561 | case KIND_LU: | ||
562 | input_report_rel(dev, REL_X, -acc); | ||
563 | input_report_rel(dev, REL_Y, -acc); | ||
564 | break; | ||
565 | case KIND_RU: | ||
566 | input_report_rel(dev, REL_X, acc); | ||
567 | input_report_rel(dev, REL_Y, -acc); | ||
568 | break; | ||
569 | case KIND_LD: | ||
570 | input_report_rel(dev, REL_X, -acc); | ||
571 | input_report_rel(dev, REL_Y, acc); | ||
572 | break; | ||
573 | case KIND_RD: | ||
574 | input_report_rel(dev, REL_X, acc); | ||
575 | input_report_rel(dev, REL_Y, acc); | ||
576 | break; | ||
577 | default: | ||
578 | dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", | ||
579 | ati_remote_tbl[index].kind); | ||
580 | } | ||
581 | input_sync(dev); | ||
582 | |||
583 | ati_remote->old_jiffies = jiffies; | ||
584 | ati_remote->old_data[0] = data[1]; | ||
585 | ati_remote->old_data[1] = data[2]; | ||
586 | } | ||
587 | } | ||
588 | |||
589 | /* | ||
590 | * ati_remote_irq_in | ||
591 | */ | ||
592 | static void ati_remote_irq_in(struct urb *urb) | ||
593 | { | ||
594 | struct ati_remote *ati_remote = urb->context; | ||
595 | int retval; | ||
596 | |||
597 | switch (urb->status) { | ||
598 | case 0: /* success */ | ||
599 | ati_remote_input_report(urb); | ||
600 | break; | ||
601 | case -ECONNRESET: /* unlink */ | ||
602 | case -ENOENT: | ||
603 | case -ESHUTDOWN: | ||
604 | dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", | ||
605 | __FUNCTION__); | ||
606 | return; | ||
607 | default: /* error */ | ||
608 | dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", | ||
609 | __FUNCTION__, urb->status); | ||
610 | } | ||
611 | |||
612 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
613 | if (retval) | ||
614 | dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", | ||
615 | __FUNCTION__, retval); | ||
616 | } | ||
617 | |||
618 | /* | ||
619 | * ati_remote_alloc_buffers | ||
620 | */ | ||
621 | static int ati_remote_alloc_buffers(struct usb_device *udev, | ||
622 | struct ati_remote *ati_remote) | ||
623 | { | ||
624 | ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, | ||
625 | &ati_remote->inbuf_dma); | ||
626 | if (!ati_remote->inbuf) | ||
627 | return -1; | ||
628 | |||
629 | ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, | ||
630 | &ati_remote->outbuf_dma); | ||
631 | if (!ati_remote->outbuf) | ||
632 | return -1; | ||
633 | |||
634 | ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
635 | if (!ati_remote->irq_urb) | ||
636 | return -1; | ||
637 | |||
638 | ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
639 | if (!ati_remote->out_urb) | ||
640 | return -1; | ||
641 | |||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | /* | ||
646 | * ati_remote_free_buffers | ||
647 | */ | ||
648 | static void ati_remote_free_buffers(struct ati_remote *ati_remote) | ||
649 | { | ||
650 | usb_free_urb(ati_remote->irq_urb); | ||
651 | usb_free_urb(ati_remote->out_urb); | ||
652 | |||
653 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | ||
654 | ati_remote->inbuf, ati_remote->inbuf_dma); | ||
655 | |||
656 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | ||
657 | ati_remote->outbuf, ati_remote->outbuf_dma); | ||
658 | } | ||
659 | |||
660 | static void ati_remote_input_init(struct ati_remote *ati_remote) | ||
661 | { | ||
662 | struct input_dev *idev = ati_remote->idev; | ||
663 | int i; | ||
664 | |||
665 | idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
666 | idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | | ||
667 | BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); | ||
668 | idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
669 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) | ||
670 | if (ati_remote_tbl[i].type == EV_KEY) | ||
671 | set_bit(ati_remote_tbl[i].code, idev->keybit); | ||
672 | |||
673 | input_set_drvdata(idev, ati_remote); | ||
674 | |||
675 | idev->open = ati_remote_open; | ||
676 | idev->close = ati_remote_close; | ||
677 | |||
678 | idev->name = ati_remote->name; | ||
679 | idev->phys = ati_remote->phys; | ||
680 | |||
681 | usb_to_input_id(ati_remote->udev, &idev->id); | ||
682 | idev->dev.parent = &ati_remote->udev->dev; | ||
683 | } | ||
684 | |||
685 | static int ati_remote_initialize(struct ati_remote *ati_remote) | ||
686 | { | ||
687 | struct usb_device *udev = ati_remote->udev; | ||
688 | int pipe, maxp; | ||
689 | |||
690 | init_waitqueue_head(&ati_remote->wait); | ||
691 | |||
692 | /* Set up irq_urb */ | ||
693 | pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); | ||
694 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
695 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | ||
696 | |||
697 | usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, | ||
698 | maxp, ati_remote_irq_in, ati_remote, | ||
699 | ati_remote->endpoint_in->bInterval); | ||
700 | ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; | ||
701 | ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
702 | |||
703 | /* Set up out_urb */ | ||
704 | pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); | ||
705 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
706 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | ||
707 | |||
708 | usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, | ||
709 | maxp, ati_remote_irq_out, ati_remote, | ||
710 | ati_remote->endpoint_out->bInterval); | ||
711 | ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; | ||
712 | ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
713 | |||
714 | /* send initialization strings */ | ||
715 | if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || | ||
716 | (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { | ||
717 | dev_err(&ati_remote->interface->dev, | ||
718 | "Initializing ati_remote hardware failed.\n"); | ||
719 | return -EIO; | ||
720 | } | ||
721 | |||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | /* | ||
726 | * ati_remote_probe | ||
727 | */ | ||
728 | static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id) | ||
729 | { | ||
730 | struct usb_device *udev = interface_to_usbdev(interface); | ||
731 | struct usb_host_interface *iface_host = interface->cur_altsetting; | ||
732 | struct usb_endpoint_descriptor *endpoint_in, *endpoint_out; | ||
733 | struct ati_remote *ati_remote; | ||
734 | struct input_dev *input_dev; | ||
735 | int err = -ENOMEM; | ||
736 | |||
737 | if (iface_host->desc.bNumEndpoints != 2) { | ||
738 | err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__); | ||
739 | return -ENODEV; | ||
740 | } | ||
741 | |||
742 | endpoint_in = &iface_host->endpoint[0].desc; | ||
743 | endpoint_out = &iface_host->endpoint[1].desc; | ||
744 | |||
745 | if (!usb_endpoint_is_int_in(endpoint_in)) { | ||
746 | err("%s: Unexpected endpoint_in\n", __FUNCTION__); | ||
747 | return -ENODEV; | ||
748 | } | ||
749 | if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) { | ||
750 | err("%s: endpoint_in message size==0? \n", __FUNCTION__); | ||
751 | return -ENODEV; | ||
752 | } | ||
753 | |||
754 | ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL); | ||
755 | input_dev = input_allocate_device(); | ||
756 | if (!ati_remote || !input_dev) | ||
757 | goto fail1; | ||
758 | |||
759 | /* Allocate URB buffers, URBs */ | ||
760 | if (ati_remote_alloc_buffers(udev, ati_remote)) | ||
761 | goto fail2; | ||
762 | |||
763 | ati_remote->endpoint_in = endpoint_in; | ||
764 | ati_remote->endpoint_out = endpoint_out; | ||
765 | ati_remote->udev = udev; | ||
766 | ati_remote->idev = input_dev; | ||
767 | ati_remote->interface = interface; | ||
768 | |||
769 | usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys)); | ||
770 | strlcpy(ati_remote->phys, "/input0", sizeof(ati_remote->phys)); | ||
771 | |||
772 | if (udev->manufacturer) | ||
773 | strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name)); | ||
774 | |||
775 | if (udev->product) | ||
776 | snprintf(ati_remote->name, sizeof(ati_remote->name), | ||
777 | "%s %s", ati_remote->name, udev->product); | ||
778 | |||
779 | if (!strlen(ati_remote->name)) | ||
780 | snprintf(ati_remote->name, sizeof(ati_remote->name), | ||
781 | DRIVER_DESC "(%04x,%04x)", | ||
782 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), | ||
783 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); | ||
784 | |||
785 | ati_remote_input_init(ati_remote); | ||
786 | |||
787 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ | ||
788 | err = ati_remote_initialize(ati_remote); | ||
789 | if (err) | ||
790 | goto fail3; | ||
791 | |||
792 | /* Set up and register input device */ | ||
793 | err = input_register_device(ati_remote->idev); | ||
794 | if (err) | ||
795 | goto fail3; | ||
796 | |||
797 | usb_set_intfdata(interface, ati_remote); | ||
798 | return 0; | ||
799 | |||
800 | fail3: usb_kill_urb(ati_remote->irq_urb); | ||
801 | usb_kill_urb(ati_remote->out_urb); | ||
802 | fail2: ati_remote_free_buffers(ati_remote); | ||
803 | fail1: input_free_device(input_dev); | ||
804 | kfree(ati_remote); | ||
805 | return err; | ||
806 | } | ||
807 | |||
808 | /* | ||
809 | * ati_remote_disconnect | ||
810 | */ | ||
811 | static void ati_remote_disconnect(struct usb_interface *interface) | ||
812 | { | ||
813 | struct ati_remote *ati_remote; | ||
814 | |||
815 | ati_remote = usb_get_intfdata(interface); | ||
816 | usb_set_intfdata(interface, NULL); | ||
817 | if (!ati_remote) { | ||
818 | warn("%s - null device?\n", __FUNCTION__); | ||
819 | return; | ||
820 | } | ||
821 | |||
822 | usb_kill_urb(ati_remote->irq_urb); | ||
823 | usb_kill_urb(ati_remote->out_urb); | ||
824 | input_unregister_device(ati_remote->idev); | ||
825 | ati_remote_free_buffers(ati_remote); | ||
826 | kfree(ati_remote); | ||
827 | } | ||
828 | |||
829 | /* | ||
830 | * ati_remote_init | ||
831 | */ | ||
832 | static int __init ati_remote_init(void) | ||
833 | { | ||
834 | int result; | ||
835 | |||
836 | result = usb_register(&ati_remote_driver); | ||
837 | if (result) | ||
838 | err("usb_register error #%d\n", result); | ||
839 | else | ||
840 | info("Registered USB driver " DRIVER_DESC " v. " DRIVER_VERSION); | ||
841 | |||
842 | return result; | ||
843 | } | ||
844 | |||
845 | /* | ||
846 | * ati_remote_exit | ||
847 | */ | ||
848 | static void __exit ati_remote_exit(void) | ||
849 | { | ||
850 | usb_deregister(&ati_remote_driver); | ||
851 | } | ||
852 | |||
853 | /* | ||
854 | * module specification | ||
855 | */ | ||
856 | |||
857 | module_init(ati_remote_init); | ||
858 | module_exit(ati_remote_exit); | ||
859 | |||
860 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
861 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
862 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c new file mode 100644 index 000000000000..1031543e5c3f --- /dev/null +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -0,0 +1,543 @@ | |||
1 | /* | ||
2 | * ati_remote2 - ATI/Philips USB RF remote driver | ||
3 | * | ||
4 | * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi> | ||
5 | * Copyright (C) 2007 Peter Stokes <linux@dadeos.freeserve.co.uk> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 | ||
9 | * as published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/usb/input.h> | ||
13 | |||
14 | #define DRIVER_DESC "ATI/Philips USB RF remote driver" | ||
15 | #define DRIVER_VERSION "0.2" | ||
16 | |||
17 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
18 | MODULE_VERSION(DRIVER_VERSION); | ||
19 | MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); | ||
20 | MODULE_LICENSE("GPL"); | ||
21 | |||
22 | /* | ||
23 | * ATI Remote Wonder II Channel Configuration | ||
24 | * | ||
25 | * The remote control can by assigned one of sixteen "channels" in order to facilitate | ||
26 | * the use of multiple remote controls within range of each other. | ||
27 | * A remote's "channel" may be altered by pressing and holding the "PC" button for | ||
28 | * approximately 3 seconds, after which the button will slowly flash the count of the | ||
29 | * currently configured "channel", using the numeric keypad enter a number between 1 and | ||
30 | * 16 and then the "PC" button again, the button will slowly flash the count of the | ||
31 | * newly configured "channel". | ||
32 | */ | ||
33 | |||
34 | static unsigned int channel_mask = 0xFFFF; | ||
35 | module_param(channel_mask, uint, 0644); | ||
36 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); | ||
37 | |||
38 | static unsigned int mode_mask = 0x1F; | ||
39 | module_param(mode_mask, uint, 0644); | ||
40 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); | ||
41 | |||
42 | static struct usb_device_id ati_remote2_id_table[] = { | ||
43 | { USB_DEVICE(0x0471, 0x0602) }, /* ATI Remote Wonder II */ | ||
44 | { } | ||
45 | }; | ||
46 | MODULE_DEVICE_TABLE(usb, ati_remote2_id_table); | ||
47 | |||
48 | static struct { | ||
49 | int hw_code; | ||
50 | int key_code; | ||
51 | } ati_remote2_key_table[] = { | ||
52 | { 0x00, KEY_0 }, | ||
53 | { 0x01, KEY_1 }, | ||
54 | { 0x02, KEY_2 }, | ||
55 | { 0x03, KEY_3 }, | ||
56 | { 0x04, KEY_4 }, | ||
57 | { 0x05, KEY_5 }, | ||
58 | { 0x06, KEY_6 }, | ||
59 | { 0x07, KEY_7 }, | ||
60 | { 0x08, KEY_8 }, | ||
61 | { 0x09, KEY_9 }, | ||
62 | { 0x0c, KEY_POWER }, | ||
63 | { 0x0d, KEY_MUTE }, | ||
64 | { 0x10, KEY_VOLUMEUP }, | ||
65 | { 0x11, KEY_VOLUMEDOWN }, | ||
66 | { 0x20, KEY_CHANNELUP }, | ||
67 | { 0x21, KEY_CHANNELDOWN }, | ||
68 | { 0x28, KEY_FORWARD }, | ||
69 | { 0x29, KEY_REWIND }, | ||
70 | { 0x2c, KEY_PLAY }, | ||
71 | { 0x30, KEY_PAUSE }, | ||
72 | { 0x31, KEY_STOP }, | ||
73 | { 0x37, KEY_RECORD }, | ||
74 | { 0x38, KEY_DVD }, | ||
75 | { 0x39, KEY_TV }, | ||
76 | { 0x54, KEY_MENU }, | ||
77 | { 0x58, KEY_UP }, | ||
78 | { 0x59, KEY_DOWN }, | ||
79 | { 0x5a, KEY_LEFT }, | ||
80 | { 0x5b, KEY_RIGHT }, | ||
81 | { 0x5c, KEY_OK }, | ||
82 | { 0x78, KEY_A }, | ||
83 | { 0x79, KEY_B }, | ||
84 | { 0x7a, KEY_C }, | ||
85 | { 0x7b, KEY_D }, | ||
86 | { 0x7c, KEY_E }, | ||
87 | { 0x7d, KEY_F }, | ||
88 | { 0x82, KEY_ENTER }, | ||
89 | { 0x8e, KEY_VENDOR }, | ||
90 | { 0x96, KEY_COFFEE }, | ||
91 | { 0xa9, BTN_LEFT }, | ||
92 | { 0xaa, BTN_RIGHT }, | ||
93 | { 0xbe, KEY_QUESTION }, | ||
94 | { 0xd5, KEY_FRONT }, | ||
95 | { 0xd0, KEY_EDIT }, | ||
96 | { 0xf9, KEY_INFO }, | ||
97 | { (0x00 << 8) | 0x3f, KEY_PROG1 }, | ||
98 | { (0x01 << 8) | 0x3f, KEY_PROG2 }, | ||
99 | { (0x02 << 8) | 0x3f, KEY_PROG3 }, | ||
100 | { (0x03 << 8) | 0x3f, KEY_PROG4 }, | ||
101 | { (0x04 << 8) | 0x3f, KEY_PC }, | ||
102 | { 0, KEY_RESERVED } | ||
103 | }; | ||
104 | |||
105 | struct ati_remote2 { | ||
106 | struct input_dev *idev; | ||
107 | struct usb_device *udev; | ||
108 | |||
109 | struct usb_interface *intf[2]; | ||
110 | struct usb_endpoint_descriptor *ep[2]; | ||
111 | struct urb *urb[2]; | ||
112 | void *buf[2]; | ||
113 | dma_addr_t buf_dma[2]; | ||
114 | |||
115 | unsigned long jiffies; | ||
116 | int mode; | ||
117 | |||
118 | char name[64]; | ||
119 | char phys[64]; | ||
120 | }; | ||
121 | |||
122 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); | ||
123 | static void ati_remote2_disconnect(struct usb_interface *interface); | ||
124 | |||
125 | static struct usb_driver ati_remote2_driver = { | ||
126 | .name = "ati_remote2", | ||
127 | .probe = ati_remote2_probe, | ||
128 | .disconnect = ati_remote2_disconnect, | ||
129 | .id_table = ati_remote2_id_table, | ||
130 | }; | ||
131 | |||
132 | static int ati_remote2_open(struct input_dev *idev) | ||
133 | { | ||
134 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | ||
135 | int r; | ||
136 | |||
137 | r = usb_submit_urb(ar2->urb[0], GFP_KERNEL); | ||
138 | if (r) { | ||
139 | dev_err(&ar2->intf[0]->dev, | ||
140 | "%s: usb_submit_urb() = %d\n", __FUNCTION__, r); | ||
141 | return r; | ||
142 | } | ||
143 | r = usb_submit_urb(ar2->urb[1], GFP_KERNEL); | ||
144 | if (r) { | ||
145 | usb_kill_urb(ar2->urb[0]); | ||
146 | dev_err(&ar2->intf[1]->dev, | ||
147 | "%s: usb_submit_urb() = %d\n", __FUNCTION__, r); | ||
148 | return r; | ||
149 | } | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static void ati_remote2_close(struct input_dev *idev) | ||
155 | { | ||
156 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | ||
157 | |||
158 | usb_kill_urb(ar2->urb[0]); | ||
159 | usb_kill_urb(ar2->urb[1]); | ||
160 | } | ||
161 | |||
162 | static void ati_remote2_input_mouse(struct ati_remote2 *ar2) | ||
163 | { | ||
164 | struct input_dev *idev = ar2->idev; | ||
165 | u8 *data = ar2->buf[0]; | ||
166 | int channel, mode; | ||
167 | |||
168 | channel = data[0] >> 4; | ||
169 | |||
170 | if (!((1 << channel) & channel_mask)) | ||
171 | return; | ||
172 | |||
173 | mode = data[0] & 0x0F; | ||
174 | |||
175 | if (mode > 4) { | ||
176 | dev_err(&ar2->intf[0]->dev, | ||
177 | "Unknown mode byte (%02x %02x %02x %02x)\n", | ||
178 | data[3], data[2], data[1], data[0]); | ||
179 | return; | ||
180 | } | ||
181 | |||
182 | if (!((1 << mode) & mode_mask)) | ||
183 | return; | ||
184 | |||
185 | input_event(idev, EV_REL, REL_X, (s8) data[1]); | ||
186 | input_event(idev, EV_REL, REL_Y, (s8) data[2]); | ||
187 | input_sync(idev); | ||
188 | } | ||
189 | |||
190 | static int ati_remote2_lookup(unsigned int hw_code) | ||
191 | { | ||
192 | int i; | ||
193 | |||
194 | for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) | ||
195 | if (ati_remote2_key_table[i].hw_code == hw_code) | ||
196 | return i; | ||
197 | |||
198 | return -1; | ||
199 | } | ||
200 | |||
201 | static void ati_remote2_input_key(struct ati_remote2 *ar2) | ||
202 | { | ||
203 | struct input_dev *idev = ar2->idev; | ||
204 | u8 *data = ar2->buf[1]; | ||
205 | int channel, mode, hw_code, index; | ||
206 | |||
207 | channel = data[0] >> 4; | ||
208 | |||
209 | if (!((1 << channel) & channel_mask)) | ||
210 | return; | ||
211 | |||
212 | mode = data[0] & 0x0F; | ||
213 | |||
214 | if (mode > 4) { | ||
215 | dev_err(&ar2->intf[1]->dev, | ||
216 | "Unknown mode byte (%02x %02x %02x %02x)\n", | ||
217 | data[3], data[2], data[1], data[0]); | ||
218 | return; | ||
219 | } | ||
220 | |||
221 | hw_code = data[2]; | ||
222 | /* | ||
223 | * Mode keys (AUX1-AUX4, PC) all generate the same code byte. | ||
224 | * Use the mode byte to figure out which one was pressed. | ||
225 | */ | ||
226 | if (hw_code == 0x3f) { | ||
227 | /* | ||
228 | * For some incomprehensible reason the mouse pad generates | ||
229 | * events which look identical to the events from the last | ||
230 | * pressed mode key. Naturally we don't want to generate key | ||
231 | * events for the mouse pad so we filter out any subsequent | ||
232 | * events from the same mode key. | ||
233 | */ | ||
234 | if (ar2->mode == mode) | ||
235 | return; | ||
236 | |||
237 | if (data[1] == 0) | ||
238 | ar2->mode = mode; | ||
239 | |||
240 | hw_code |= mode << 8; | ||
241 | } | ||
242 | |||
243 | if (!((1 << mode) & mode_mask)) | ||
244 | return; | ||
245 | |||
246 | index = ati_remote2_lookup(hw_code); | ||
247 | if (index < 0) { | ||
248 | dev_err(&ar2->intf[1]->dev, | ||
249 | "Unknown code byte (%02x %02x %02x %02x)\n", | ||
250 | data[3], data[2], data[1], data[0]); | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | switch (data[1]) { | ||
255 | case 0: /* release */ | ||
256 | break; | ||
257 | case 1: /* press */ | ||
258 | ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_DELAY]); | ||
259 | break; | ||
260 | case 2: /* repeat */ | ||
261 | |||
262 | /* No repeat for mouse buttons. */ | ||
263 | if (ati_remote2_key_table[index].key_code == BTN_LEFT || | ||
264 | ati_remote2_key_table[index].key_code == BTN_RIGHT) | ||
265 | return; | ||
266 | |||
267 | if (!time_after_eq(jiffies, ar2->jiffies)) | ||
268 | return; | ||
269 | |||
270 | ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_PERIOD]); | ||
271 | break; | ||
272 | default: | ||
273 | dev_err(&ar2->intf[1]->dev, | ||
274 | "Unknown state byte (%02x %02x %02x %02x)\n", | ||
275 | data[3], data[2], data[1], data[0]); | ||
276 | return; | ||
277 | } | ||
278 | |||
279 | input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]); | ||
280 | input_sync(idev); | ||
281 | } | ||
282 | |||
283 | static void ati_remote2_complete_mouse(struct urb *urb) | ||
284 | { | ||
285 | struct ati_remote2 *ar2 = urb->context; | ||
286 | int r; | ||
287 | |||
288 | switch (urb->status) { | ||
289 | case 0: | ||
290 | ati_remote2_input_mouse(ar2); | ||
291 | break; | ||
292 | case -ENOENT: | ||
293 | case -EILSEQ: | ||
294 | case -ECONNRESET: | ||
295 | case -ESHUTDOWN: | ||
296 | dev_dbg(&ar2->intf[0]->dev, | ||
297 | "%s(): urb status = %d\n", __FUNCTION__, urb->status); | ||
298 | return; | ||
299 | default: | ||
300 | dev_err(&ar2->intf[0]->dev, | ||
301 | "%s(): urb status = %d\n", __FUNCTION__, urb->status); | ||
302 | } | ||
303 | |||
304 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
305 | if (r) | ||
306 | dev_err(&ar2->intf[0]->dev, | ||
307 | "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r); | ||
308 | } | ||
309 | |||
310 | static void ati_remote2_complete_key(struct urb *urb) | ||
311 | { | ||
312 | struct ati_remote2 *ar2 = urb->context; | ||
313 | int r; | ||
314 | |||
315 | switch (urb->status) { | ||
316 | case 0: | ||
317 | ati_remote2_input_key(ar2); | ||
318 | break; | ||
319 | case -ENOENT: | ||
320 | case -EILSEQ: | ||
321 | case -ECONNRESET: | ||
322 | case -ESHUTDOWN: | ||
323 | dev_dbg(&ar2->intf[1]->dev, | ||
324 | "%s(): urb status = %d\n", __FUNCTION__, urb->status); | ||
325 | return; | ||
326 | default: | ||
327 | dev_err(&ar2->intf[1]->dev, | ||
328 | "%s(): urb status = %d\n", __FUNCTION__, urb->status); | ||
329 | } | ||
330 | |||
331 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
332 | if (r) | ||
333 | dev_err(&ar2->intf[1]->dev, | ||
334 | "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r); | ||
335 | } | ||
336 | |||
337 | static int ati_remote2_input_init(struct ati_remote2 *ar2) | ||
338 | { | ||
339 | struct input_dev *idev; | ||
340 | int i, retval; | ||
341 | |||
342 | idev = input_allocate_device(); | ||
343 | if (!idev) | ||
344 | return -ENOMEM; | ||
345 | |||
346 | ar2->idev = idev; | ||
347 | input_set_drvdata(idev, ar2); | ||
348 | |||
349 | idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL); | ||
350 | idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT); | ||
351 | idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
352 | for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) | ||
353 | set_bit(ati_remote2_key_table[i].key_code, idev->keybit); | ||
354 | |||
355 | idev->rep[REP_DELAY] = 250; | ||
356 | idev->rep[REP_PERIOD] = 33; | ||
357 | |||
358 | idev->open = ati_remote2_open; | ||
359 | idev->close = ati_remote2_close; | ||
360 | |||
361 | idev->name = ar2->name; | ||
362 | idev->phys = ar2->phys; | ||
363 | |||
364 | usb_to_input_id(ar2->udev, &idev->id); | ||
365 | idev->dev.parent = &ar2->udev->dev; | ||
366 | |||
367 | retval = input_register_device(idev); | ||
368 | if (retval) | ||
369 | input_free_device(idev); | ||
370 | |||
371 | return retval; | ||
372 | } | ||
373 | |||
374 | static int ati_remote2_urb_init(struct ati_remote2 *ar2) | ||
375 | { | ||
376 | struct usb_device *udev = ar2->udev; | ||
377 | int i, pipe, maxp; | ||
378 | |||
379 | for (i = 0; i < 2; i++) { | ||
380 | ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]); | ||
381 | if (!ar2->buf[i]) | ||
382 | return -ENOMEM; | ||
383 | |||
384 | ar2->urb[i] = usb_alloc_urb(0, GFP_KERNEL); | ||
385 | if (!ar2->urb[i]) | ||
386 | return -ENOMEM; | ||
387 | |||
388 | pipe = usb_rcvintpipe(udev, ar2->ep[i]->bEndpointAddress); | ||
389 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
390 | maxp = maxp > 4 ? 4 : maxp; | ||
391 | |||
392 | usb_fill_int_urb(ar2->urb[i], udev, pipe, ar2->buf[i], maxp, | ||
393 | i ? ati_remote2_complete_key : ati_remote2_complete_mouse, | ||
394 | ar2, ar2->ep[i]->bInterval); | ||
395 | ar2->urb[i]->transfer_dma = ar2->buf_dma[i]; | ||
396 | ar2->urb[i]->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
397 | } | ||
398 | |||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) | ||
403 | { | ||
404 | int i; | ||
405 | |||
406 | for (i = 0; i < 2; i++) { | ||
407 | usb_free_urb(ar2->urb[i]); | ||
408 | usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); | ||
409 | } | ||
410 | } | ||
411 | |||
412 | static int ati_remote2_setup(struct ati_remote2 *ar2) | ||
413 | { | ||
414 | int r, i, channel; | ||
415 | |||
416 | /* | ||
417 | * Configure receiver to only accept input from remote "channel" | ||
418 | * channel == 0 -> Accept input from any remote channel | ||
419 | * channel == 1 -> Only accept input from remote channel 1 | ||
420 | * channel == 2 -> Only accept input from remote channel 2 | ||
421 | * ... | ||
422 | * channel == 16 -> Only accept input from remote channel 16 | ||
423 | */ | ||
424 | |||
425 | channel = 0; | ||
426 | for (i = 0; i < 16; i++) { | ||
427 | if ((1 << i) & channel_mask) { | ||
428 | if (!(~(1 << i) & 0xFFFF & channel_mask)) | ||
429 | channel = i + 1; | ||
430 | break; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | r = usb_control_msg(ar2->udev, usb_sndctrlpipe(ar2->udev, 0), | ||
435 | 0x20, | ||
436 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
437 | channel, 0x0, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
438 | if (r) { | ||
439 | dev_err(&ar2->udev->dev, "%s - failed to set channel due to error: %d\n", | ||
440 | __FUNCTION__, r); | ||
441 | return r; | ||
442 | } | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) | ||
448 | { | ||
449 | struct usb_device *udev = interface_to_usbdev(interface); | ||
450 | struct usb_host_interface *alt = interface->cur_altsetting; | ||
451 | struct ati_remote2 *ar2; | ||
452 | int r; | ||
453 | |||
454 | if (alt->desc.bInterfaceNumber) | ||
455 | return -ENODEV; | ||
456 | |||
457 | ar2 = kzalloc(sizeof (struct ati_remote2), GFP_KERNEL); | ||
458 | if (!ar2) | ||
459 | return -ENOMEM; | ||
460 | |||
461 | ar2->udev = udev; | ||
462 | |||
463 | ar2->intf[0] = interface; | ||
464 | ar2->ep[0] = &alt->endpoint[0].desc; | ||
465 | |||
466 | ar2->intf[1] = usb_ifnum_to_if(udev, 1); | ||
467 | r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2); | ||
468 | if (r) | ||
469 | goto fail1; | ||
470 | alt = ar2->intf[1]->cur_altsetting; | ||
471 | ar2->ep[1] = &alt->endpoint[0].desc; | ||
472 | |||
473 | r = ati_remote2_urb_init(ar2); | ||
474 | if (r) | ||
475 | goto fail2; | ||
476 | |||
477 | r = ati_remote2_setup(ar2); | ||
478 | if (r) | ||
479 | goto fail2; | ||
480 | |||
481 | usb_make_path(udev, ar2->phys, sizeof(ar2->phys)); | ||
482 | strlcat(ar2->phys, "/input0", sizeof(ar2->phys)); | ||
483 | |||
484 | strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); | ||
485 | |||
486 | r = ati_remote2_input_init(ar2); | ||
487 | if (r) | ||
488 | goto fail2; | ||
489 | |||
490 | usb_set_intfdata(interface, ar2); | ||
491 | |||
492 | return 0; | ||
493 | |||
494 | fail2: | ||
495 | ati_remote2_urb_cleanup(ar2); | ||
496 | |||
497 | usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); | ||
498 | fail1: | ||
499 | kfree(ar2); | ||
500 | |||
501 | return r; | ||
502 | } | ||
503 | |||
504 | static void ati_remote2_disconnect(struct usb_interface *interface) | ||
505 | { | ||
506 | struct ati_remote2 *ar2; | ||
507 | struct usb_host_interface *alt = interface->cur_altsetting; | ||
508 | |||
509 | if (alt->desc.bInterfaceNumber) | ||
510 | return; | ||
511 | |||
512 | ar2 = usb_get_intfdata(interface); | ||
513 | usb_set_intfdata(interface, NULL); | ||
514 | |||
515 | input_unregister_device(ar2->idev); | ||
516 | |||
517 | ati_remote2_urb_cleanup(ar2); | ||
518 | |||
519 | usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); | ||
520 | |||
521 | kfree(ar2); | ||
522 | } | ||
523 | |||
524 | static int __init ati_remote2_init(void) | ||
525 | { | ||
526 | int r; | ||
527 | |||
528 | r = usb_register(&ati_remote2_driver); | ||
529 | if (r) | ||
530 | printk(KERN_ERR "ati_remote2: usb_register() = %d\n", r); | ||
531 | else | ||
532 | printk(KERN_INFO "ati_remote2: " DRIVER_DESC " " DRIVER_VERSION "\n"); | ||
533 | |||
534 | return r; | ||
535 | } | ||
536 | |||
537 | static void __exit ati_remote2_exit(void) | ||
538 | { | ||
539 | usb_deregister(&ati_remote2_driver); | ||
540 | } | ||
541 | |||
542 | module_init(ati_remote2_init); | ||
543 | module_exit(ati_remote2_exit); | ||
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c new file mode 100644 index 000000000000..1bffc9fa98c2 --- /dev/null +++ b/drivers/input/misc/keyspan_remote.c | |||
@@ -0,0 +1,592 @@ | |||
1 | /* | ||
2 | * keyspan_remote: USB driver for the Keyspan DMR | ||
3 | * | ||
4 | * Copyright (C) 2005 Zymeta Corporation - Michael Downey (downey@zymeta.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | * This driver has been put together with the support of Innosys, Inc. | ||
11 | * and Keyspan, Inc the manufacturers of the Keyspan USB DMR product. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/usb/input.h> | ||
21 | |||
22 | #define DRIVER_VERSION "v0.1" | ||
23 | #define DRIVER_AUTHOR "Michael Downey <downey@zymeta.com>" | ||
24 | #define DRIVER_DESC "Driver for the USB Keyspan remote control." | ||
25 | #define DRIVER_LICENSE "GPL" | ||
26 | |||
27 | /* Parameters that can be passed to the driver. */ | ||
28 | static int debug; | ||
29 | module_param(debug, int, 0444); | ||
30 | MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); | ||
31 | |||
32 | /* Vendor and product ids */ | ||
33 | #define USB_KEYSPAN_VENDOR_ID 0x06CD | ||
34 | #define USB_KEYSPAN_PRODUCT_UIA11 0x0202 | ||
35 | |||
36 | /* Defines for converting the data from the remote. */ | ||
37 | #define ZERO 0x18 | ||
38 | #define ZERO_MASK 0x1F /* 5 bits for a 0 */ | ||
39 | #define ONE 0x3C | ||
40 | #define ONE_MASK 0x3F /* 6 bits for a 1 */ | ||
41 | #define SYNC 0x3F80 | ||
42 | #define SYNC_MASK 0x3FFF /* 14 bits for a SYNC sequence */ | ||
43 | #define STOP 0x00 | ||
44 | #define STOP_MASK 0x1F /* 5 bits for the STOP sequence */ | ||
45 | #define GAP 0xFF | ||
46 | |||
47 | #define RECV_SIZE 8 /* The UIA-11 type have a 8 byte limit. */ | ||
48 | |||
49 | /* table of devices that work with this driver */ | ||
50 | static struct usb_device_id keyspan_table[] = { | ||
51 | { USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) }, | ||
52 | { } /* Terminating entry */ | ||
53 | }; | ||
54 | |||
55 | /* Structure to store all the real stuff that a remote sends to us. */ | ||
56 | struct keyspan_message { | ||
57 | u16 system; | ||
58 | u8 button; | ||
59 | u8 toggle; | ||
60 | }; | ||
61 | |||
62 | /* Structure used for all the bit testing magic needed to be done. */ | ||
63 | struct bit_tester { | ||
64 | u32 tester; | ||
65 | int len; | ||
66 | int pos; | ||
67 | int bits_left; | ||
68 | u8 buffer[32]; | ||
69 | }; | ||
70 | |||
71 | /* Structure to hold all of our driver specific stuff */ | ||
72 | struct usb_keyspan { | ||
73 | char name[128]; | ||
74 | char phys[64]; | ||
75 | struct usb_device* udev; | ||
76 | struct input_dev *input; | ||
77 | struct usb_interface* interface; | ||
78 | struct usb_endpoint_descriptor* in_endpoint; | ||
79 | struct urb* irq_urb; | ||
80 | int open; | ||
81 | dma_addr_t in_dma; | ||
82 | unsigned char* in_buffer; | ||
83 | |||
84 | /* variables used to parse messages from remote. */ | ||
85 | struct bit_tester data; | ||
86 | int stage; | ||
87 | int toggle; | ||
88 | }; | ||
89 | |||
90 | /* | ||
91 | * Table that maps the 31 possible keycodes to input keys. | ||
92 | * Currently there are 15 and 17 button models so RESERVED codes | ||
93 | * are blank areas in the mapping. | ||
94 | */ | ||
95 | static const int keyspan_key_table[] = { | ||
96 | KEY_RESERVED, /* 0 is just a place holder. */ | ||
97 | KEY_RESERVED, | ||
98 | KEY_STOP, | ||
99 | KEY_PLAYCD, | ||
100 | KEY_RESERVED, | ||
101 | KEY_PREVIOUSSONG, | ||
102 | KEY_REWIND, | ||
103 | KEY_FORWARD, | ||
104 | KEY_NEXTSONG, | ||
105 | KEY_RESERVED, | ||
106 | KEY_RESERVED, | ||
107 | KEY_RESERVED, | ||
108 | KEY_PAUSE, | ||
109 | KEY_VOLUMEUP, | ||
110 | KEY_RESERVED, | ||
111 | KEY_RESERVED, | ||
112 | KEY_RESERVED, | ||
113 | KEY_VOLUMEDOWN, | ||
114 | KEY_RESERVED, | ||
115 | KEY_UP, | ||
116 | KEY_RESERVED, | ||
117 | KEY_MUTE, | ||
118 | KEY_LEFT, | ||
119 | KEY_ENTER, | ||
120 | KEY_RIGHT, | ||
121 | KEY_RESERVED, | ||
122 | KEY_RESERVED, | ||
123 | KEY_DOWN, | ||
124 | KEY_RESERVED, | ||
125 | KEY_KPASTERISK, | ||
126 | KEY_RESERVED, | ||
127 | KEY_MENU | ||
128 | }; | ||
129 | |||
130 | static struct usb_driver keyspan_driver; | ||
131 | |||
132 | /* | ||
133 | * Debug routine that prints out what we've received from the remote. | ||
134 | */ | ||
135 | static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/ | ||
136 | { | ||
137 | char codes[4 * RECV_SIZE]; | ||
138 | int i; | ||
139 | |||
140 | for (i = 0; i < RECV_SIZE; i++) | ||
141 | snprintf(codes + i * 3, 4, "%02x ", dev->in_buffer[i]); | ||
142 | |||
143 | dev_info(&dev->udev->dev, "%s\n", codes); | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * Routine that manages the bit_tester structure. It makes sure that there are | ||
148 | * at least bits_needed bits loaded into the tester. | ||
149 | */ | ||
150 | static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) | ||
151 | { | ||
152 | if (dev->data.bits_left >= bits_needed) | ||
153 | return 0; | ||
154 | |||
155 | /* | ||
156 | * Somehow we've missed the last message. The message will be repeated | ||
157 | * though so it's not too big a deal | ||
158 | */ | ||
159 | if (dev->data.pos >= dev->data.len) { | ||
160 | dev_dbg(&dev->udev->dev, | ||
161 | "%s - Error ran out of data. pos: %d, len: %d\n", | ||
162 | __FUNCTION__, dev->data.pos, dev->data.len); | ||
163 | return -1; | ||
164 | } | ||
165 | |||
166 | /* Load as much as we can into the tester. */ | ||
167 | while ((dev->data.bits_left + 7 < (sizeof(dev->data.tester) * 8)) && | ||
168 | (dev->data.pos < dev->data.len)) { | ||
169 | dev->data.tester += (dev->data.buffer[dev->data.pos++] << dev->data.bits_left); | ||
170 | dev->data.bits_left += 8; | ||
171 | } | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * Routine that handles all the logic needed to parse out the message from the remote. | ||
178 | */ | ||
179 | static void keyspan_check_data(struct usb_keyspan *remote) | ||
180 | { | ||
181 | int i; | ||
182 | int found = 0; | ||
183 | struct keyspan_message message; | ||
184 | |||
185 | switch(remote->stage) { | ||
186 | case 0: | ||
187 | /* | ||
188 | * In stage 0 we want to find the start of a message. The remote sends a 0xFF as filler. | ||
189 | * So the first byte that isn't a FF should be the start of a new message. | ||
190 | */ | ||
191 | for (i = 0; i < RECV_SIZE && remote->in_buffer[i] == GAP; ++i); | ||
192 | |||
193 | if (i < RECV_SIZE) { | ||
194 | memcpy(remote->data.buffer, remote->in_buffer, RECV_SIZE); | ||
195 | remote->data.len = RECV_SIZE; | ||
196 | remote->data.pos = 0; | ||
197 | remote->data.tester = 0; | ||
198 | remote->data.bits_left = 0; | ||
199 | remote->stage = 1; | ||
200 | } | ||
201 | break; | ||
202 | |||
203 | case 1: | ||
204 | /* | ||
205 | * Stage 1 we should have 16 bytes and should be able to detect a | ||
206 | * SYNC. The SYNC is 14 bits, 7 0's and then 7 1's. | ||
207 | */ | ||
208 | memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE); | ||
209 | remote->data.len += RECV_SIZE; | ||
210 | |||
211 | found = 0; | ||
212 | while ((remote->data.bits_left >= 14 || remote->data.pos < remote->data.len) && !found) { | ||
213 | for (i = 0; i < 8; ++i) { | ||
214 | if (keyspan_load_tester(remote, 14) != 0) { | ||
215 | remote->stage = 0; | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | if ((remote->data.tester & SYNC_MASK) == SYNC) { | ||
220 | remote->data.tester = remote->data.tester >> 14; | ||
221 | remote->data.bits_left -= 14; | ||
222 | found = 1; | ||
223 | break; | ||
224 | } else { | ||
225 | remote->data.tester = remote->data.tester >> 1; | ||
226 | --remote->data.bits_left; | ||
227 | } | ||
228 | } | ||
229 | } | ||
230 | |||
231 | if (!found) { | ||
232 | remote->stage = 0; | ||
233 | remote->data.len = 0; | ||
234 | } else { | ||
235 | remote->stage = 2; | ||
236 | } | ||
237 | break; | ||
238 | |||
239 | case 2: | ||
240 | /* | ||
241 | * Stage 2 we should have 24 bytes which will be enough for a full | ||
242 | * message. We need to parse out the system code, button code, | ||
243 | * toggle code, and stop. | ||
244 | */ | ||
245 | memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE); | ||
246 | remote->data.len += RECV_SIZE; | ||
247 | |||
248 | message.system = 0; | ||
249 | for (i = 0; i < 9; i++) { | ||
250 | keyspan_load_tester(remote, 6); | ||
251 | |||
252 | if ((remote->data.tester & ZERO_MASK) == ZERO) { | ||
253 | message.system = message.system << 1; | ||
254 | remote->data.tester = remote->data.tester >> 5; | ||
255 | remote->data.bits_left -= 5; | ||
256 | } else if ((remote->data.tester & ONE_MASK) == ONE) { | ||
257 | message.system = (message.system << 1) + 1; | ||
258 | remote->data.tester = remote->data.tester >> 6; | ||
259 | remote->data.bits_left -= 6; | ||
260 | } else { | ||
261 | err("%s - Unknown sequence found in system data.\n", __FUNCTION__); | ||
262 | remote->stage = 0; | ||
263 | return; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | message.button = 0; | ||
268 | for (i = 0; i < 5; i++) { | ||
269 | keyspan_load_tester(remote, 6); | ||
270 | |||
271 | if ((remote->data.tester & ZERO_MASK) == ZERO) { | ||
272 | message.button = message.button << 1; | ||
273 | remote->data.tester = remote->data.tester >> 5; | ||
274 | remote->data.bits_left -= 5; | ||
275 | } else if ((remote->data.tester & ONE_MASK) == ONE) { | ||
276 | message.button = (message.button << 1) + 1; | ||
277 | remote->data.tester = remote->data.tester >> 6; | ||
278 | remote->data.bits_left -= 6; | ||
279 | } else { | ||
280 | err("%s - Unknown sequence found in button data.\n", __FUNCTION__); | ||
281 | remote->stage = 0; | ||
282 | return; | ||
283 | } | ||
284 | } | ||
285 | |||
286 | keyspan_load_tester(remote, 6); | ||
287 | if ((remote->data.tester & ZERO_MASK) == ZERO) { | ||
288 | message.toggle = 0; | ||
289 | remote->data.tester = remote->data.tester >> 5; | ||
290 | remote->data.bits_left -= 5; | ||
291 | } else if ((remote->data.tester & ONE_MASK) == ONE) { | ||
292 | message.toggle = 1; | ||
293 | remote->data.tester = remote->data.tester >> 6; | ||
294 | remote->data.bits_left -= 6; | ||
295 | } else { | ||
296 | err("%s - Error in message, invalid toggle.\n", __FUNCTION__); | ||
297 | remote->stage = 0; | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | keyspan_load_tester(remote, 5); | ||
302 | if ((remote->data.tester & STOP_MASK) == STOP) { | ||
303 | remote->data.tester = remote->data.tester >> 5; | ||
304 | remote->data.bits_left -= 5; | ||
305 | } else { | ||
306 | err("Bad message recieved, no stop bit found.\n"); | ||
307 | } | ||
308 | |||
309 | dev_dbg(&remote->udev->dev, | ||
310 | "%s found valid message: system: %d, button: %d, toggle: %d\n", | ||
311 | __FUNCTION__, message.system, message.button, message.toggle); | ||
312 | |||
313 | if (message.toggle != remote->toggle) { | ||
314 | input_report_key(remote->input, keyspan_key_table[message.button], 1); | ||
315 | input_report_key(remote->input, keyspan_key_table[message.button], 0); | ||
316 | input_sync(remote->input); | ||
317 | remote->toggle = message.toggle; | ||
318 | } | ||
319 | |||
320 | remote->stage = 0; | ||
321 | break; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | /* | ||
326 | * Routine for sending all the initialization messages to the remote. | ||
327 | */ | ||
328 | static int keyspan_setup(struct usb_device* dev) | ||
329 | { | ||
330 | int retval = 0; | ||
331 | |||
332 | retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
333 | 0x11, 0x40, 0x5601, 0x0, NULL, 0, 0); | ||
334 | if (retval) { | ||
335 | dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n", | ||
336 | __FUNCTION__, retval); | ||
337 | return(retval); | ||
338 | } | ||
339 | |||
340 | retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
341 | 0x44, 0x40, 0x0, 0x0, NULL, 0, 0); | ||
342 | if (retval) { | ||
343 | dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n", | ||
344 | __FUNCTION__, retval); | ||
345 | return(retval); | ||
346 | } | ||
347 | |||
348 | retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
349 | 0x22, 0x40, 0x0, 0x0, NULL, 0, 0); | ||
350 | if (retval) { | ||
351 | dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n", | ||
352 | __FUNCTION__, retval); | ||
353 | return(retval); | ||
354 | } | ||
355 | |||
356 | dev_dbg(&dev->dev, "%s - Setup complete.\n", __FUNCTION__); | ||
357 | return(retval); | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * Routine used to handle a new message that has come in. | ||
362 | */ | ||
363 | static void keyspan_irq_recv(struct urb *urb) | ||
364 | { | ||
365 | struct usb_keyspan *dev = urb->context; | ||
366 | int retval; | ||
367 | |||
368 | /* Check our status in case we need to bail out early. */ | ||
369 | switch (urb->status) { | ||
370 | case 0: | ||
371 | break; | ||
372 | |||
373 | /* Device went away so don't keep trying to read from it. */ | ||
374 | case -ECONNRESET: | ||
375 | case -ENOENT: | ||
376 | case -ESHUTDOWN: | ||
377 | return; | ||
378 | |||
379 | default: | ||
380 | goto resubmit; | ||
381 | break; | ||
382 | } | ||
383 | |||
384 | if (debug) | ||
385 | keyspan_print(dev); | ||
386 | |||
387 | keyspan_check_data(dev); | ||
388 | |||
389 | resubmit: | ||
390 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
391 | if (retval) | ||
392 | err ("%s - usb_submit_urb failed with result: %d", __FUNCTION__, retval); | ||
393 | } | ||
394 | |||
395 | static int keyspan_open(struct input_dev *dev) | ||
396 | { | ||
397 | struct usb_keyspan *remote = input_get_drvdata(dev); | ||
398 | |||
399 | remote->irq_urb->dev = remote->udev; | ||
400 | if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) | ||
401 | return -EIO; | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static void keyspan_close(struct input_dev *dev) | ||
407 | { | ||
408 | struct usb_keyspan *remote = input_get_drvdata(dev); | ||
409 | |||
410 | usb_kill_urb(remote->irq_urb); | ||
411 | } | ||
412 | |||
413 | static struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_interface *iface) | ||
414 | { | ||
415 | |||
416 | struct usb_endpoint_descriptor *endpoint; | ||
417 | int i; | ||
418 | |||
419 | for (i = 0; i < iface->desc.bNumEndpoints; ++i) { | ||
420 | endpoint = &iface->endpoint[i].desc; | ||
421 | |||
422 | if (usb_endpoint_is_int_in(endpoint)) { | ||
423 | /* we found our interrupt in endpoint */ | ||
424 | return endpoint; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | return NULL; | ||
429 | } | ||
430 | |||
431 | /* | ||
432 | * Routine that sets up the driver to handle a specific USB device detected on the bus. | ||
433 | */ | ||
434 | static int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id) | ||
435 | { | ||
436 | struct usb_device *udev = interface_to_usbdev(interface); | ||
437 | struct usb_endpoint_descriptor *endpoint; | ||
438 | struct usb_keyspan *remote; | ||
439 | struct input_dev *input_dev; | ||
440 | int i, error; | ||
441 | |||
442 | endpoint = keyspan_get_in_endpoint(interface->cur_altsetting); | ||
443 | if (!endpoint) | ||
444 | return -ENODEV; | ||
445 | |||
446 | remote = kzalloc(sizeof(*remote), GFP_KERNEL); | ||
447 | input_dev = input_allocate_device(); | ||
448 | if (!remote || !input_dev) { | ||
449 | error = -ENOMEM; | ||
450 | goto fail1; | ||
451 | } | ||
452 | |||
453 | remote->udev = udev; | ||
454 | remote->input = input_dev; | ||
455 | remote->interface = interface; | ||
456 | remote->in_endpoint = endpoint; | ||
457 | remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ | ||
458 | |||
459 | remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); | ||
460 | if (!remote->in_buffer) { | ||
461 | error = -ENOMEM; | ||
462 | goto fail1; | ||
463 | } | ||
464 | |||
465 | remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
466 | if (!remote->irq_urb) { | ||
467 | error = -ENOMEM; | ||
468 | goto fail2; | ||
469 | } | ||
470 | |||
471 | error = keyspan_setup(udev); | ||
472 | if (error) { | ||
473 | error = -ENODEV; | ||
474 | goto fail3; | ||
475 | } | ||
476 | |||
477 | if (udev->manufacturer) | ||
478 | strlcpy(remote->name, udev->manufacturer, sizeof(remote->name)); | ||
479 | |||
480 | if (udev->product) { | ||
481 | if (udev->manufacturer) | ||
482 | strlcat(remote->name, " ", sizeof(remote->name)); | ||
483 | strlcat(remote->name, udev->product, sizeof(remote->name)); | ||
484 | } | ||
485 | |||
486 | if (!strlen(remote->name)) | ||
487 | snprintf(remote->name, sizeof(remote->name), | ||
488 | "USB Keyspan Remote %04x:%04x", | ||
489 | le16_to_cpu(udev->descriptor.idVendor), | ||
490 | le16_to_cpu(udev->descriptor.idProduct)); | ||
491 | |||
492 | usb_make_path(udev, remote->phys, sizeof(remote->phys)); | ||
493 | strlcat(remote->phys, "/input0", sizeof(remote->phys)); | ||
494 | |||
495 | input_dev->name = remote->name; | ||
496 | input_dev->phys = remote->phys; | ||
497 | usb_to_input_id(udev, &input_dev->id); | ||
498 | input_dev->dev.parent = &interface->dev; | ||
499 | |||
500 | input_dev->evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */ | ||
501 | for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++) | ||
502 | if (keyspan_key_table[i] != KEY_RESERVED) | ||
503 | set_bit(keyspan_key_table[i], input_dev->keybit); | ||
504 | |||
505 | input_set_drvdata(input_dev, remote); | ||
506 | |||
507 | input_dev->open = keyspan_open; | ||
508 | input_dev->close = keyspan_close; | ||
509 | |||
510 | /* | ||
511 | * Initialize the URB to access the device. The urb gets sent to the device in keyspan_open() | ||
512 | */ | ||
513 | usb_fill_int_urb(remote->irq_urb, | ||
514 | remote->udev, usb_rcvintpipe(remote->udev, remote->in_endpoint->bEndpointAddress), | ||
515 | remote->in_buffer, RECV_SIZE, keyspan_irq_recv, remote, | ||
516 | remote->in_endpoint->bInterval); | ||
517 | remote->irq_urb->transfer_dma = remote->in_dma; | ||
518 | remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
519 | |||
520 | /* we can register the device now, as it is ready */ | ||
521 | error = input_register_device(remote->input); | ||
522 | if (error) | ||
523 | goto fail3; | ||
524 | |||
525 | /* save our data pointer in this interface device */ | ||
526 | usb_set_intfdata(interface, remote); | ||
527 | |||
528 | return 0; | ||
529 | |||
530 | fail3: usb_free_urb(remote->irq_urb); | ||
531 | fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); | ||
532 | fail1: kfree(remote); | ||
533 | input_free_device(input_dev); | ||
534 | |||
535 | return error; | ||
536 | } | ||
537 | |||
538 | /* | ||
539 | * Routine called when a device is disconnected from the USB. | ||
540 | */ | ||
541 | static void keyspan_disconnect(struct usb_interface *interface) | ||
542 | { | ||
543 | struct usb_keyspan *remote; | ||
544 | |||
545 | remote = usb_get_intfdata(interface); | ||
546 | usb_set_intfdata(interface, NULL); | ||
547 | |||
548 | if (remote) { /* We have a valid driver structure so clean up everything we allocated. */ | ||
549 | input_unregister_device(remote->input); | ||
550 | usb_kill_urb(remote->irq_urb); | ||
551 | usb_free_urb(remote->irq_urb); | ||
552 | usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); | ||
553 | kfree(remote); | ||
554 | } | ||
555 | } | ||
556 | |||
557 | /* | ||
558 | * Standard driver set up sections | ||
559 | */ | ||
560 | static struct usb_driver keyspan_driver = | ||
561 | { | ||
562 | .name = "keyspan_remote", | ||
563 | .probe = keyspan_probe, | ||
564 | .disconnect = keyspan_disconnect, | ||
565 | .id_table = keyspan_table | ||
566 | }; | ||
567 | |||
568 | static int __init usb_keyspan_init(void) | ||
569 | { | ||
570 | int result; | ||
571 | |||
572 | /* register this driver with the USB subsystem */ | ||
573 | result = usb_register(&keyspan_driver); | ||
574 | if (result) | ||
575 | err("usb_register failed. Error number %d\n", result); | ||
576 | |||
577 | return result; | ||
578 | } | ||
579 | |||
580 | static void __exit usb_keyspan_exit(void) | ||
581 | { | ||
582 | /* deregister this driver with the USB subsystem */ | ||
583 | usb_deregister(&keyspan_driver); | ||
584 | } | ||
585 | |||
586 | module_init(usb_keyspan_init); | ||
587 | module_exit(usb_keyspan_exit); | ||
588 | |||
589 | MODULE_DEVICE_TABLE(usb, keyspan_table); | ||
590 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
591 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
592 | MODULE_LICENSE(DRIVER_LICENSE); | ||
diff --git a/drivers/input/misc/map_to_7segment.h b/drivers/input/misc/map_to_7segment.h new file mode 100644 index 000000000000..a424094d9fe2 --- /dev/null +++ b/drivers/input/misc/map_to_7segment.h | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * drivers/usb/input/map_to_7segment.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of | ||
9 | * the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #ifndef MAP_TO_7SEGMENT_H | ||
22 | #define MAP_TO_7SEGMENT_H | ||
23 | |||
24 | /* This file provides translation primitives and tables for the conversion | ||
25 | * of (ASCII) characters to a 7-segments notation. | ||
26 | * | ||
27 | * The 7 segment's wikipedia notation below is used as standard. | ||
28 | * See: http://en.wikipedia.org/wiki/Seven_segment_display | ||
29 | * | ||
30 | * Notation: +-a-+ | ||
31 | * f b | ||
32 | * +-g-+ | ||
33 | * e c | ||
34 | * +-d-+ | ||
35 | * | ||
36 | * Usage: | ||
37 | * | ||
38 | * Register a map variable, and fill it with a character set: | ||
39 | * static SEG7_DEFAULT_MAP(map_seg7); | ||
40 | * | ||
41 | * | ||
42 | * Then use for conversion: | ||
43 | * seg7 = map_to_seg7(&map_seg7, some_char); | ||
44 | * ... | ||
45 | * | ||
46 | * In device drivers it is recommended, if required, to make the char map | ||
47 | * accessible via the sysfs interface using the following scheme: | ||
48 | * | ||
49 | * static ssize_t show_map(struct device *dev, char *buf) { | ||
50 | * memcpy(buf, &map_seg7, sizeof(map_seg7)); | ||
51 | * return sizeof(map_seg7); | ||
52 | * } | ||
53 | * static ssize_t store_map(struct device *dev, const char *buf, size_t cnt) { | ||
54 | * if(cnt != sizeof(map_seg7)) | ||
55 | * return -EINVAL; | ||
56 | * memcpy(&map_seg7, buf, cnt); | ||
57 | * return cnt; | ||
58 | * } | ||
59 | * static DEVICE_ATTR(map_seg7, PERMS_RW, show_map, store_map); | ||
60 | * | ||
61 | * History: | ||
62 | * 2005-05-31 RFC linux-kernel@vger.kernel.org | ||
63 | */ | ||
64 | #include <linux/errno.h> | ||
65 | |||
66 | |||
67 | #define BIT_SEG7_A 0 | ||
68 | #define BIT_SEG7_B 1 | ||
69 | #define BIT_SEG7_C 2 | ||
70 | #define BIT_SEG7_D 3 | ||
71 | #define BIT_SEG7_E 4 | ||
72 | #define BIT_SEG7_F 5 | ||
73 | #define BIT_SEG7_G 6 | ||
74 | #define BIT_SEG7_RESERVED 7 | ||
75 | |||
76 | struct seg7_conversion_map { | ||
77 | unsigned char table[128]; | ||
78 | }; | ||
79 | |||
80 | static inline int map_to_seg7(struct seg7_conversion_map *map, int c) | ||
81 | { | ||
82 | return c >= 0 && c < sizeof(map->table) ? map->table[c] : -EINVAL; | ||
83 | } | ||
84 | |||
85 | #define SEG7_CONVERSION_MAP(_name, _map) \ | ||
86 | struct seg7_conversion_map _name = { .table = { _map } } | ||
87 | |||
88 | /* | ||
89 | * It is recommended to use a facility that allows user space to redefine | ||
90 | * custom character sets for LCD devices. Please use a sysfs interface | ||
91 | * as described above. | ||
92 | */ | ||
93 | #define MAP_TO_SEG7_SYSFS_FILE "map_seg7" | ||
94 | |||
95 | /******************************************************************************* | ||
96 | * ASCII conversion table | ||
97 | ******************************************************************************/ | ||
98 | |||
99 | #define _SEG7(l,a,b,c,d,e,f,g) \ | ||
100 | ( a<<BIT_SEG7_A | b<<BIT_SEG7_B | c<<BIT_SEG7_C | d<<BIT_SEG7_D | \ | ||
101 | e<<BIT_SEG7_E | f<<BIT_SEG7_F | g<<BIT_SEG7_G ) | ||
102 | |||
103 | #define _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ | ||
104 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
105 | |||
106 | #define _MAP_33_47_ASCII_SEG7_SYMBOL \ | ||
107 | _SEG7('!',0,0,0,0,1,1,0), _SEG7('"',0,1,0,0,0,1,0), _SEG7('#',0,1,1,0,1,1,0),\ | ||
108 | _SEG7('$',1,0,1,1,0,1,1), _SEG7('%',0,0,1,0,0,1,0), _SEG7('&',1,0,1,1,1,1,1),\ | ||
109 | _SEG7('\'',0,0,0,0,0,1,0),_SEG7('(',1,0,0,1,1,1,0), _SEG7(')',1,1,1,1,0,0,0),\ | ||
110 | _SEG7('*',0,1,1,0,1,1,1), _SEG7('+',0,1,1,0,0,0,1), _SEG7(',',0,0,0,0,1,0,0),\ | ||
111 | _SEG7('-',0,0,0,0,0,0,1), _SEG7('.',0,0,0,0,1,0,0), _SEG7('/',0,1,0,0,1,0,1), | ||
112 | |||
113 | #define _MAP_48_57_ASCII_SEG7_NUMERIC \ | ||
114 | _SEG7('0',1,1,1,1,1,1,0), _SEG7('1',0,1,1,0,0,0,0), _SEG7('2',1,1,0,1,1,0,1),\ | ||
115 | _SEG7('3',1,1,1,1,0,0,1), _SEG7('4',0,1,1,0,0,1,1), _SEG7('5',1,0,1,1,0,1,1),\ | ||
116 | _SEG7('6',1,0,1,1,1,1,1), _SEG7('7',1,1,1,0,0,0,0), _SEG7('8',1,1,1,1,1,1,1),\ | ||
117 | _SEG7('9',1,1,1,1,0,1,1), | ||
118 | |||
119 | #define _MAP_58_64_ASCII_SEG7_SYMBOL \ | ||
120 | _SEG7(':',0,0,0,1,0,0,1), _SEG7(';',0,0,0,1,0,0,1), _SEG7('<',1,0,0,0,0,1,1),\ | ||
121 | _SEG7('=',0,0,0,1,0,0,1), _SEG7('>',1,1,0,0,0,0,1), _SEG7('?',1,1,1,0,0,1,0),\ | ||
122 | _SEG7('@',1,1,0,1,1,1,1), | ||
123 | |||
124 | #define _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \ | ||
125 | _SEG7('A',1,1,1,0,1,1,1), _SEG7('B',1,1,1,1,1,1,1), _SEG7('C',1,0,0,1,1,1,0),\ | ||
126 | _SEG7('D',1,1,1,1,1,1,0), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\ | ||
127 | _SEG7('G',1,1,1,1,0,1,1), _SEG7('H',0,1,1,0,1,1,1), _SEG7('I',0,1,1,0,0,0,0),\ | ||
128 | _SEG7('J',0,1,1,1,0,0,0), _SEG7('K',0,1,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\ | ||
129 | _SEG7('M',1,1,1,0,1,1,0), _SEG7('N',1,1,1,0,1,1,0), _SEG7('O',1,1,1,1,1,1,0),\ | ||
130 | _SEG7('P',1,1,0,0,1,1,1), _SEG7('Q',1,1,1,1,1,1,0), _SEG7('R',1,1,1,0,1,1,1),\ | ||
131 | _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('U',0,1,1,1,1,1,0),\ | ||
132 | _SEG7('V',0,1,1,1,1,1,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\ | ||
133 | _SEG7('Y',0,1,1,0,0,1,1), _SEG7('Z',1,1,0,1,1,0,1), | ||
134 | |||
135 | #define _MAP_91_96_ASCII_SEG7_SYMBOL \ | ||
136 | _SEG7('[',1,0,0,1,1,1,0), _SEG7('\\',0,0,1,0,0,1,1),_SEG7(']',1,1,1,1,0,0,0),\ | ||
137 | _SEG7('^',1,1,0,0,0,1,0), _SEG7('_',0,0,0,1,0,0,0), _SEG7('`',0,1,0,0,0,0,0), | ||
138 | |||
139 | #define _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
140 | _SEG7('A',1,1,1,0,1,1,1), _SEG7('b',0,0,1,1,1,1,1), _SEG7('c',0,0,0,1,1,0,1),\ | ||
141 | _SEG7('d',0,1,1,1,1,0,1), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\ | ||
142 | _SEG7('G',1,1,1,1,0,1,1), _SEG7('h',0,0,1,0,1,1,1), _SEG7('i',0,0,1,0,0,0,0),\ | ||
143 | _SEG7('j',0,0,1,1,0,0,0), _SEG7('k',0,0,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\ | ||
144 | _SEG7('M',1,1,1,0,1,1,0), _SEG7('n',0,0,1,0,1,0,1), _SEG7('o',0,0,1,1,1,0,1),\ | ||
145 | _SEG7('P',1,1,0,0,1,1,1), _SEG7('q',1,1,1,0,0,1,1), _SEG7('r',0,0,0,0,1,0,1),\ | ||
146 | _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('u',0,0,1,1,1,0,0),\ | ||
147 | _SEG7('v',0,0,1,1,1,0,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\ | ||
148 | _SEG7('y',0,1,1,1,0,1,1), _SEG7('Z',1,1,0,1,1,0,1), | ||
149 | |||
150 | #define _MAP_123_126_ASCII_SEG7_SYMBOL \ | ||
151 | _SEG7('{',1,0,0,1,1,1,0), _SEG7('|',0,0,0,0,1,1,0), _SEG7('}',1,1,1,1,0,0,0),\ | ||
152 | _SEG7('~',1,0,0,0,0,0,0), | ||
153 | |||
154 | /* Maps */ | ||
155 | |||
156 | /* This set tries to map as close as possible to the visible characteristics | ||
157 | * of the ASCII symbol, lowercase and uppercase letters may differ in | ||
158 | * presentation on the display. | ||
159 | */ | ||
160 | #define MAP_ASCII7SEG_ALPHANUM \ | ||
161 | _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ | ||
162 | _MAP_33_47_ASCII_SEG7_SYMBOL \ | ||
163 | _MAP_48_57_ASCII_SEG7_NUMERIC \ | ||
164 | _MAP_58_64_ASCII_SEG7_SYMBOL \ | ||
165 | _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \ | ||
166 | _MAP_91_96_ASCII_SEG7_SYMBOL \ | ||
167 | _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
168 | _MAP_123_126_ASCII_SEG7_SYMBOL | ||
169 | |||
170 | /* This set tries to map as close as possible to the symbolic characteristics | ||
171 | * of the ASCII character for maximum discrimination. | ||
172 | * For now this means all alpha chars are in lower case representations. | ||
173 | * (This for example facilitates the use of hex numbers with uppercase input.) | ||
174 | */ | ||
175 | #define MAP_ASCII7SEG_ALPHANUM_LC \ | ||
176 | _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ | ||
177 | _MAP_33_47_ASCII_SEG7_SYMBOL \ | ||
178 | _MAP_48_57_ASCII_SEG7_NUMERIC \ | ||
179 | _MAP_58_64_ASCII_SEG7_SYMBOL \ | ||
180 | _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
181 | _MAP_91_96_ASCII_SEG7_SYMBOL \ | ||
182 | _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
183 | _MAP_123_126_ASCII_SEG7_SYMBOL | ||
184 | |||
185 | #define SEG7_DEFAULT_MAP(_name) \ | ||
186 | SEG7_CONVERSION_MAP(_name,MAP_ASCII7SEG_ALPHANUM) | ||
187 | |||
188 | #endif /* MAP_TO_7SEGMENT_H */ | ||
189 | |||
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c new file mode 100644 index 000000000000..448a470d28f2 --- /dev/null +++ b/drivers/input/misc/powermate.c | |||
@@ -0,0 +1,463 @@ | |||
1 | /* | ||
2 | * A driver for the Griffin Technology, Inc. "PowerMate" USB controller dial. | ||
3 | * | ||
4 | * v1.1, (c)2002 William R Sowerbutts <will@sowerbutts.com> | ||
5 | * | ||
6 | * This device is a anodised aluminium knob which connects over USB. It can measure | ||
7 | * clockwise and anticlockwise rotation. The dial also acts as a pushbutton with | ||
8 | * a spring for automatic release. The base contains a pair of LEDs which illuminate | ||
9 | * the translucent base. It rotates without limit and reports its relative rotation | ||
10 | * back to the host when polled by the USB controller. | ||
11 | * | ||
12 | * Testing with the knob I have has shown that it measures approximately 94 "clicks" | ||
13 | * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was | ||
14 | * a variable speed cordless electric drill) has shown that the device can measure | ||
15 | * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from | ||
16 | * the host. If it counts more than 7 clicks before it is polled, it will wrap back | ||
17 | * to zero and start counting again. This was at quite high speed, however, almost | ||
18 | * certainly faster than the human hand could turn it. Griffin say that it loses a | ||
19 | * pulse or two on a direction change; the granularity is so fine that I never | ||
20 | * noticed this in practice. | ||
21 | * | ||
22 | * The device's microcontroller can be programmed to set the LED to either a constant | ||
23 | * intensity, or to a rhythmic pulsing. Several patterns and speeds are available. | ||
24 | * | ||
25 | * Griffin were very happy to provide documentation and free hardware for development. | ||
26 | * | ||
27 | * Some userspace tools are available on the web: http://sowerbutts.com/powermate/ | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | #include <linux/usb/input.h> | ||
37 | |||
38 | #define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ | ||
39 | #define POWERMATE_PRODUCT_NEW 0x0410 /* Griffin PowerMate */ | ||
40 | #define POWERMATE_PRODUCT_OLD 0x04AA /* Griffin soundKnob */ | ||
41 | |||
42 | #define CONTOUR_VENDOR 0x05f3 /* Contour Design, Inc. */ | ||
43 | #define CONTOUR_JOG 0x0240 /* Jog and Shuttle */ | ||
44 | |||
45 | /* these are the command codes we send to the device */ | ||
46 | #define SET_STATIC_BRIGHTNESS 0x01 | ||
47 | #define SET_PULSE_ASLEEP 0x02 | ||
48 | #define SET_PULSE_AWAKE 0x03 | ||
49 | #define SET_PULSE_MODE 0x04 | ||
50 | |||
51 | /* these refer to bits in the powermate_device's requires_update field. */ | ||
52 | #define UPDATE_STATIC_BRIGHTNESS (1<<0) | ||
53 | #define UPDATE_PULSE_ASLEEP (1<<1) | ||
54 | #define UPDATE_PULSE_AWAKE (1<<2) | ||
55 | #define UPDATE_PULSE_MODE (1<<3) | ||
56 | |||
57 | /* at least two versions of the hardware exist, with differing payload | ||
58 | sizes. the first three bytes always contain the "interesting" data in | ||
59 | the relevant format. */ | ||
60 | #define POWERMATE_PAYLOAD_SIZE_MAX 6 | ||
61 | #define POWERMATE_PAYLOAD_SIZE_MIN 3 | ||
62 | struct powermate_device { | ||
63 | signed char *data; | ||
64 | dma_addr_t data_dma; | ||
65 | struct urb *irq, *config; | ||
66 | struct usb_ctrlrequest *configcr; | ||
67 | dma_addr_t configcr_dma; | ||
68 | struct usb_device *udev; | ||
69 | struct input_dev *input; | ||
70 | spinlock_t lock; | ||
71 | int static_brightness; | ||
72 | int pulse_speed; | ||
73 | int pulse_table; | ||
74 | int pulse_asleep; | ||
75 | int pulse_awake; | ||
76 | int requires_update; // physical settings which are out of sync | ||
77 | char phys[64]; | ||
78 | }; | ||
79 | |||
80 | static char pm_name_powermate[] = "Griffin PowerMate"; | ||
81 | static char pm_name_soundknob[] = "Griffin SoundKnob"; | ||
82 | |||
83 | static void powermate_config_complete(struct urb *urb); | ||
84 | |||
85 | /* Callback for data arriving from the PowerMate over the USB interrupt pipe */ | ||
86 | static void powermate_irq(struct urb *urb) | ||
87 | { | ||
88 | struct powermate_device *pm = urb->context; | ||
89 | int retval; | ||
90 | |||
91 | switch (urb->status) { | ||
92 | case 0: | ||
93 | /* success */ | ||
94 | break; | ||
95 | case -ECONNRESET: | ||
96 | case -ENOENT: | ||
97 | case -ESHUTDOWN: | ||
98 | /* this urb is terminated, clean up */ | ||
99 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
100 | return; | ||
101 | default: | ||
102 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
103 | goto exit; | ||
104 | } | ||
105 | |||
106 | /* handle updates to device state */ | ||
107 | input_report_key(pm->input, BTN_0, pm->data[0] & 0x01); | ||
108 | input_report_rel(pm->input, REL_DIAL, pm->data[1]); | ||
109 | input_sync(pm->input); | ||
110 | |||
111 | exit: | ||
112 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
113 | if (retval) | ||
114 | err ("%s - usb_submit_urb failed with result %d", | ||
115 | __FUNCTION__, retval); | ||
116 | } | ||
117 | |||
118 | /* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ | ||
119 | static void powermate_sync_state(struct powermate_device *pm) | ||
120 | { | ||
121 | if (pm->requires_update == 0) | ||
122 | return; /* no updates are required */ | ||
123 | if (pm->config->status == -EINPROGRESS) | ||
124 | return; /* an update is already in progress; it'll issue this update when it completes */ | ||
125 | |||
126 | if (pm->requires_update & UPDATE_PULSE_ASLEEP){ | ||
127 | pm->configcr->wValue = cpu_to_le16( SET_PULSE_ASLEEP ); | ||
128 | pm->configcr->wIndex = cpu_to_le16( pm->pulse_asleep ? 1 : 0 ); | ||
129 | pm->requires_update &= ~UPDATE_PULSE_ASLEEP; | ||
130 | }else if (pm->requires_update & UPDATE_PULSE_AWAKE){ | ||
131 | pm->configcr->wValue = cpu_to_le16( SET_PULSE_AWAKE ); | ||
132 | pm->configcr->wIndex = cpu_to_le16( pm->pulse_awake ? 1 : 0 ); | ||
133 | pm->requires_update &= ~UPDATE_PULSE_AWAKE; | ||
134 | }else if (pm->requires_update & UPDATE_PULSE_MODE){ | ||
135 | int op, arg; | ||
136 | /* the powermate takes an operation and an argument for its pulse algorithm. | ||
137 | the operation can be: | ||
138 | 0: divide the speed | ||
139 | 1: pulse at normal speed | ||
140 | 2: multiply the speed | ||
141 | the argument only has an effect for operations 0 and 2, and ranges between | ||
142 | 1 (least effect) to 255 (maximum effect). | ||
143 | |||
144 | thus, several states are equivalent and are coalesced into one state. | ||
145 | |||
146 | we map this onto a range from 0 to 510, with: | ||
147 | 0 -- 254 -- use divide (0 = slowest) | ||
148 | 255 -- use normal speed | ||
149 | 256 -- 510 -- use multiple (510 = fastest). | ||
150 | |||
151 | Only values of 'arg' quite close to 255 are particularly useful/spectacular. | ||
152 | */ | ||
153 | if (pm->pulse_speed < 255) { | ||
154 | op = 0; // divide | ||
155 | arg = 255 - pm->pulse_speed; | ||
156 | } else if (pm->pulse_speed > 255) { | ||
157 | op = 2; // multiply | ||
158 | arg = pm->pulse_speed - 255; | ||
159 | } else { | ||
160 | op = 1; // normal speed | ||
161 | arg = 0; // can be any value | ||
162 | } | ||
163 | pm->configcr->wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE ); | ||
164 | pm->configcr->wIndex = cpu_to_le16( (arg << 8) | op ); | ||
165 | pm->requires_update &= ~UPDATE_PULSE_MODE; | ||
166 | } else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS) { | ||
167 | pm->configcr->wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS ); | ||
168 | pm->configcr->wIndex = cpu_to_le16( pm->static_brightness ); | ||
169 | pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS; | ||
170 | } else { | ||
171 | printk(KERN_ERR "powermate: unknown update required"); | ||
172 | pm->requires_update = 0; /* fudge the bug */ | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | /* printk("powermate: %04x %04x\n", pm->configcr->wValue, pm->configcr->wIndex); */ | ||
177 | |||
178 | pm->configcr->bRequestType = 0x41; /* vendor request */ | ||
179 | pm->configcr->bRequest = 0x01; | ||
180 | pm->configcr->wLength = 0; | ||
181 | |||
182 | usb_fill_control_urb(pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0), | ||
183 | (void *) pm->configcr, NULL, 0, | ||
184 | powermate_config_complete, pm); | ||
185 | pm->config->setup_dma = pm->configcr_dma; | ||
186 | pm->config->transfer_flags |= URB_NO_SETUP_DMA_MAP; | ||
187 | |||
188 | if (usb_submit_urb(pm->config, GFP_ATOMIC)) | ||
189 | printk(KERN_ERR "powermate: usb_submit_urb(config) failed"); | ||
190 | } | ||
191 | |||
192 | /* Called when our asynchronous control message completes. We may need to issue another immediately */ | ||
193 | static void powermate_config_complete(struct urb *urb) | ||
194 | { | ||
195 | struct powermate_device *pm = urb->context; | ||
196 | unsigned long flags; | ||
197 | |||
198 | if (urb->status) | ||
199 | printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); | ||
200 | |||
201 | spin_lock_irqsave(&pm->lock, flags); | ||
202 | powermate_sync_state(pm); | ||
203 | spin_unlock_irqrestore(&pm->lock, flags); | ||
204 | } | ||
205 | |||
206 | /* Set the LED up as described and begin the sync with the hardware if required */ | ||
207 | static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, | ||
208 | int pulse_table, int pulse_asleep, int pulse_awake) | ||
209 | { | ||
210 | unsigned long flags; | ||
211 | |||
212 | if (pulse_speed < 0) | ||
213 | pulse_speed = 0; | ||
214 | if (pulse_table < 0) | ||
215 | pulse_table = 0; | ||
216 | if (pulse_speed > 510) | ||
217 | pulse_speed = 510; | ||
218 | if (pulse_table > 2) | ||
219 | pulse_table = 2; | ||
220 | |||
221 | pulse_asleep = !!pulse_asleep; | ||
222 | pulse_awake = !!pulse_awake; | ||
223 | |||
224 | |||
225 | spin_lock_irqsave(&pm->lock, flags); | ||
226 | |||
227 | /* mark state updates which are required */ | ||
228 | if (static_brightness != pm->static_brightness) { | ||
229 | pm->static_brightness = static_brightness; | ||
230 | pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; | ||
231 | } | ||
232 | if (pulse_asleep != pm->pulse_asleep) { | ||
233 | pm->pulse_asleep = pulse_asleep; | ||
234 | pm->requires_update |= (UPDATE_PULSE_ASLEEP | UPDATE_STATIC_BRIGHTNESS); | ||
235 | } | ||
236 | if (pulse_awake != pm->pulse_awake) { | ||
237 | pm->pulse_awake = pulse_awake; | ||
238 | pm->requires_update |= (UPDATE_PULSE_AWAKE | UPDATE_STATIC_BRIGHTNESS); | ||
239 | } | ||
240 | if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table) { | ||
241 | pm->pulse_speed = pulse_speed; | ||
242 | pm->pulse_table = pulse_table; | ||
243 | pm->requires_update |= UPDATE_PULSE_MODE; | ||
244 | } | ||
245 | |||
246 | powermate_sync_state(pm); | ||
247 | |||
248 | spin_unlock_irqrestore(&pm->lock, flags); | ||
249 | } | ||
250 | |||
251 | /* Callback from the Input layer when an event arrives from userspace to configure the LED */ | ||
252 | static int powermate_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int _value) | ||
253 | { | ||
254 | unsigned int command = (unsigned int)_value; | ||
255 | struct powermate_device *pm = input_get_drvdata(dev); | ||
256 | |||
257 | if (type == EV_MSC && code == MSC_PULSELED){ | ||
258 | /* | ||
259 | bits 0- 7: 8 bits: LED brightness | ||
260 | bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. | ||
261 | bits 17-18: 2 bits: pulse table (0, 1, 2 valid) | ||
262 | bit 19: 1 bit : pulse whilst asleep? | ||
263 | bit 20: 1 bit : pulse constantly? | ||
264 | */ | ||
265 | int static_brightness = command & 0xFF; // bits 0-7 | ||
266 | int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 | ||
267 | int pulse_table = (command >> 17) & 0x3; // bits 17-18 | ||
268 | int pulse_asleep = (command >> 19) & 0x1; // bit 19 | ||
269 | int pulse_awake = (command >> 20) & 0x1; // bit 20 | ||
270 | |||
271 | powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); | ||
272 | } | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm) | ||
278 | { | ||
279 | pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX, | ||
280 | GFP_ATOMIC, &pm->data_dma); | ||
281 | if (!pm->data) | ||
282 | return -1; | ||
283 | |||
284 | pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)), | ||
285 | GFP_ATOMIC, &pm->configcr_dma); | ||
286 | if (!pm->configcr) | ||
287 | return -1; | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static void powermate_free_buffers(struct usb_device *udev, struct powermate_device *pm) | ||
293 | { | ||
294 | usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX, | ||
295 | pm->data, pm->data_dma); | ||
296 | usb_buffer_free(udev, sizeof(*(pm->configcr)), | ||
297 | pm->configcr, pm->configcr_dma); | ||
298 | } | ||
299 | |||
300 | /* Called whenever a USB device matching one in our supported devices table is connected */ | ||
301 | static int powermate_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
302 | { | ||
303 | struct usb_device *udev = interface_to_usbdev (intf); | ||
304 | struct usb_host_interface *interface; | ||
305 | struct usb_endpoint_descriptor *endpoint; | ||
306 | struct powermate_device *pm; | ||
307 | struct input_dev *input_dev; | ||
308 | int pipe, maxp; | ||
309 | int error = -ENOMEM; | ||
310 | |||
311 | interface = intf->cur_altsetting; | ||
312 | endpoint = &interface->endpoint[0].desc; | ||
313 | if (!usb_endpoint_is_int_in(endpoint)) | ||
314 | return -EIO; | ||
315 | |||
316 | usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
317 | 0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
318 | 0, interface->desc.bInterfaceNumber, NULL, 0, | ||
319 | USB_CTRL_SET_TIMEOUT); | ||
320 | |||
321 | pm = kzalloc(sizeof(struct powermate_device), GFP_KERNEL); | ||
322 | input_dev = input_allocate_device(); | ||
323 | if (!pm || !input_dev) | ||
324 | goto fail1; | ||
325 | |||
326 | if (powermate_alloc_buffers(udev, pm)) | ||
327 | goto fail2; | ||
328 | |||
329 | pm->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
330 | if (!pm->irq) | ||
331 | goto fail2; | ||
332 | |||
333 | pm->config = usb_alloc_urb(0, GFP_KERNEL); | ||
334 | if (!pm->config) | ||
335 | goto fail3; | ||
336 | |||
337 | pm->udev = udev; | ||
338 | pm->input = input_dev; | ||
339 | |||
340 | usb_make_path(udev, pm->phys, sizeof(pm->phys)); | ||
341 | strlcpy(pm->phys, "/input0", sizeof(pm->phys)); | ||
342 | |||
343 | spin_lock_init(&pm->lock); | ||
344 | |||
345 | switch (le16_to_cpu(udev->descriptor.idProduct)) { | ||
346 | case POWERMATE_PRODUCT_NEW: | ||
347 | input_dev->name = pm_name_powermate; | ||
348 | break; | ||
349 | case POWERMATE_PRODUCT_OLD: | ||
350 | input_dev->name = pm_name_soundknob; | ||
351 | break; | ||
352 | default: | ||
353 | input_dev->name = pm_name_soundknob; | ||
354 | printk(KERN_WARNING "powermate: unknown product id %04x\n", | ||
355 | le16_to_cpu(udev->descriptor.idProduct)); | ||
356 | } | ||
357 | |||
358 | input_dev->phys = pm->phys; | ||
359 | usb_to_input_id(udev, &input_dev->id); | ||
360 | input_dev->dev.parent = &intf->dev; | ||
361 | |||
362 | input_set_drvdata(input_dev, pm); | ||
363 | |||
364 | input_dev->event = powermate_input_event; | ||
365 | |||
366 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC); | ||
367 | input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); | ||
368 | input_dev->relbit[LONG(REL_DIAL)] = BIT(REL_DIAL); | ||
369 | input_dev->mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED); | ||
370 | |||
371 | /* get a handle to the interrupt data pipe */ | ||
372 | pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); | ||
373 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
374 | |||
375 | if (maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX) { | ||
376 | printk(KERN_WARNING "powermate: Expected payload of %d--%d bytes, found %d bytes!\n", | ||
377 | POWERMATE_PAYLOAD_SIZE_MIN, POWERMATE_PAYLOAD_SIZE_MAX, maxp); | ||
378 | maxp = POWERMATE_PAYLOAD_SIZE_MAX; | ||
379 | } | ||
380 | |||
381 | usb_fill_int_urb(pm->irq, udev, pipe, pm->data, | ||
382 | maxp, powermate_irq, | ||
383 | pm, endpoint->bInterval); | ||
384 | pm->irq->transfer_dma = pm->data_dma; | ||
385 | pm->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
386 | |||
387 | /* register our interrupt URB with the USB system */ | ||
388 | if (usb_submit_urb(pm->irq, GFP_KERNEL)) { | ||
389 | error = -EIO; | ||
390 | goto fail4; | ||
391 | } | ||
392 | |||
393 | error = input_register_device(pm->input); | ||
394 | if (error) | ||
395 | goto fail5; | ||
396 | |||
397 | |||
398 | /* force an update of everything */ | ||
399 | pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; | ||
400 | powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters | ||
401 | |||
402 | usb_set_intfdata(intf, pm); | ||
403 | return 0; | ||
404 | |||
405 | fail5: usb_kill_urb(pm->irq); | ||
406 | fail4: usb_free_urb(pm->config); | ||
407 | fail3: usb_free_urb(pm->irq); | ||
408 | fail2: powermate_free_buffers(udev, pm); | ||
409 | fail1: input_free_device(input_dev); | ||
410 | kfree(pm); | ||
411 | return error; | ||
412 | } | ||
413 | |||
414 | /* Called when a USB device we've accepted ownership of is removed */ | ||
415 | static void powermate_disconnect(struct usb_interface *intf) | ||
416 | { | ||
417 | struct powermate_device *pm = usb_get_intfdata (intf); | ||
418 | |||
419 | usb_set_intfdata(intf, NULL); | ||
420 | if (pm) { | ||
421 | pm->requires_update = 0; | ||
422 | usb_kill_urb(pm->irq); | ||
423 | input_unregister_device(pm->input); | ||
424 | usb_free_urb(pm->irq); | ||
425 | usb_free_urb(pm->config); | ||
426 | powermate_free_buffers(interface_to_usbdev(intf), pm); | ||
427 | |||
428 | kfree(pm); | ||
429 | } | ||
430 | } | ||
431 | |||
432 | static struct usb_device_id powermate_devices [] = { | ||
433 | { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_NEW) }, | ||
434 | { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_OLD) }, | ||
435 | { USB_DEVICE(CONTOUR_VENDOR, CONTOUR_JOG) }, | ||
436 | { } /* Terminating entry */ | ||
437 | }; | ||
438 | |||
439 | MODULE_DEVICE_TABLE (usb, powermate_devices); | ||
440 | |||
441 | static struct usb_driver powermate_driver = { | ||
442 | .name = "powermate", | ||
443 | .probe = powermate_probe, | ||
444 | .disconnect = powermate_disconnect, | ||
445 | .id_table = powermate_devices, | ||
446 | }; | ||
447 | |||
448 | static int __init powermate_init(void) | ||
449 | { | ||
450 | return usb_register(&powermate_driver); | ||
451 | } | ||
452 | |||
453 | static void __exit powermate_cleanup(void) | ||
454 | { | ||
455 | usb_deregister(&powermate_driver); | ||
456 | } | ||
457 | |||
458 | module_init(powermate_init); | ||
459 | module_exit(powermate_cleanup); | ||
460 | |||
461 | MODULE_AUTHOR( "William R Sowerbutts" ); | ||
462 | MODULE_DESCRIPTION( "Griffin Technology, Inc PowerMate driver" ); | ||
463 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 031467eadd31..a56ad4ba8fe2 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/input.h> | ||
37 | #include <linux/smp_lock.h> | 36 | #include <linux/smp_lock.h> |
38 | #include <linux/fs.h> | 37 | #include <linux/fs.h> |
39 | #include <linux/miscdevice.h> | 38 | #include <linux/miscdevice.h> |
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c new file mode 100644 index 000000000000..ab15880fd566 --- /dev/null +++ b/drivers/input/misc/yealink.c | |||
@@ -0,0 +1,1004 @@ | |||
1 | /* | ||
2 | * drivers/usb/input/yealink.c | ||
3 | * | ||
4 | * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of | ||
9 | * the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | /* | ||
21 | * Description: | ||
22 | * Driver for the USB-P1K voip usb phone. | ||
23 | * This device is produced by Yealink Network Technology Co Ltd | ||
24 | * but may be branded under several names: | ||
25 | * - Yealink usb-p1k | ||
26 | * - Tiptel 115 | ||
27 | * - ... | ||
28 | * | ||
29 | * This driver is based on: | ||
30 | * - the usbb2k-api http://savannah.nongnu.org/projects/usbb2k-api/ | ||
31 | * - information from http://memeteau.free.fr/usbb2k | ||
32 | * - the xpad-driver drivers/input/joystick/xpad.c | ||
33 | * | ||
34 | * Thanks to: | ||
35 | * - Olivier Vandorpe, for providing the usbb2k-api. | ||
36 | * - Martin Diehl, for spotting my memory allocation bug. | ||
37 | * | ||
38 | * History: | ||
39 | * 20050527 henk First version, functional keyboard. Keyboard events | ||
40 | * will pop-up on the ../input/eventX bus. | ||
41 | * 20050531 henk Added led, LCD, dialtone and sysfs interface. | ||
42 | * 20050610 henk Cleanups, make it ready for public consumption. | ||
43 | * 20050630 henk Cleanups, fixes in response to comments. | ||
44 | * 20050701 henk sysfs write serialisation, fix potential unload races | ||
45 | * 20050801 henk Added ringtone, restructure USB | ||
46 | * 20050816 henk Merge 2.6.13-rc6 | ||
47 | */ | ||
48 | |||
49 | #include <linux/kernel.h> | ||
50 | #include <linux/init.h> | ||
51 | #include <linux/slab.h> | ||
52 | #include <linux/module.h> | ||
53 | #include <linux/rwsem.h> | ||
54 | #include <linux/usb/input.h> | ||
55 | |||
56 | #include "map_to_7segment.h" | ||
57 | #include "yealink.h" | ||
58 | |||
59 | #define DRIVER_VERSION "yld-20051230" | ||
60 | #define DRIVER_AUTHOR "Henk Vergonet" | ||
61 | #define DRIVER_DESC "Yealink phone driver" | ||
62 | |||
63 | #define YEALINK_POLLING_FREQUENCY 10 /* in [Hz] */ | ||
64 | |||
65 | struct yld_status { | ||
66 | u8 lcd[24]; | ||
67 | u8 led; | ||
68 | u8 dialtone; | ||
69 | u8 ringtone; | ||
70 | u8 keynum; | ||
71 | } __attribute__ ((packed)); | ||
72 | |||
73 | /* | ||
74 | * Register the LCD segment and icon map | ||
75 | */ | ||
76 | #define _LOC(k,l) { .a = (k), .m = (l) } | ||
77 | #define _SEG(t, a, am, b, bm, c, cm, d, dm, e, em, f, fm, g, gm) \ | ||
78 | { .type = (t), \ | ||
79 | .u = { .s = { _LOC(a, am), _LOC(b, bm), _LOC(c, cm), \ | ||
80 | _LOC(d, dm), _LOC(e, em), _LOC(g, gm), \ | ||
81 | _LOC(f, fm) } } } | ||
82 | #define _PIC(t, h, hm, n) \ | ||
83 | { .type = (t), \ | ||
84 | .u = { .p = { .name = (n), .a = (h), .m = (hm) } } } | ||
85 | |||
86 | static const struct lcd_segment_map { | ||
87 | char type; | ||
88 | union { | ||
89 | struct pictogram_map { | ||
90 | u8 a,m; | ||
91 | char name[10]; | ||
92 | } p; | ||
93 | struct segment_map { | ||
94 | u8 a,m; | ||
95 | } s[7]; | ||
96 | } u; | ||
97 | } lcdMap[] = { | ||
98 | #include "yealink.h" | ||
99 | }; | ||
100 | |||
101 | struct yealink_dev { | ||
102 | struct input_dev *idev; /* input device */ | ||
103 | struct usb_device *udev; /* usb device */ | ||
104 | |||
105 | /* irq input channel */ | ||
106 | struct yld_ctl_packet *irq_data; | ||
107 | dma_addr_t irq_dma; | ||
108 | struct urb *urb_irq; | ||
109 | |||
110 | /* control output channel */ | ||
111 | struct yld_ctl_packet *ctl_data; | ||
112 | dma_addr_t ctl_dma; | ||
113 | struct usb_ctrlrequest *ctl_req; | ||
114 | dma_addr_t ctl_req_dma; | ||
115 | struct urb *urb_ctl; | ||
116 | |||
117 | char phys[64]; /* physical device path */ | ||
118 | |||
119 | u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */ | ||
120 | int key_code; /* last reported key */ | ||
121 | |||
122 | int stat_ix; | ||
123 | union { | ||
124 | struct yld_status s; | ||
125 | u8 b[sizeof(struct yld_status)]; | ||
126 | } master, copy; | ||
127 | }; | ||
128 | |||
129 | |||
130 | /******************************************************************************* | ||
131 | * Yealink lcd interface | ||
132 | ******************************************************************************/ | ||
133 | |||
134 | /* | ||
135 | * Register a default 7 segment character set | ||
136 | */ | ||
137 | static SEG7_DEFAULT_MAP(map_seg7); | ||
138 | |||
139 | /* Display a char, | ||
140 | * char '\9' and '\n' are placeholders and do not overwrite the original text. | ||
141 | * A space will always hide an icon. | ||
142 | */ | ||
143 | static int setChar(struct yealink_dev *yld, int el, int chr) | ||
144 | { | ||
145 | int i, a, m, val; | ||
146 | |||
147 | if (el >= ARRAY_SIZE(lcdMap)) | ||
148 | return -EINVAL; | ||
149 | |||
150 | if (chr == '\t' || chr == '\n') | ||
151 | return 0; | ||
152 | |||
153 | yld->lcdMap[el] = chr; | ||
154 | |||
155 | if (lcdMap[el].type == '.') { | ||
156 | a = lcdMap[el].u.p.a; | ||
157 | m = lcdMap[el].u.p.m; | ||
158 | if (chr != ' ') | ||
159 | yld->master.b[a] |= m; | ||
160 | else | ||
161 | yld->master.b[a] &= ~m; | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | val = map_to_seg7(&map_seg7, chr); | ||
166 | for (i = 0; i < ARRAY_SIZE(lcdMap[0].u.s); i++) { | ||
167 | m = lcdMap[el].u.s[i].m; | ||
168 | |||
169 | if (m == 0) | ||
170 | continue; | ||
171 | |||
172 | a = lcdMap[el].u.s[i].a; | ||
173 | if (val & 1) | ||
174 | yld->master.b[a] |= m; | ||
175 | else | ||
176 | yld->master.b[a] &= ~m; | ||
177 | val = val >> 1; | ||
178 | } | ||
179 | return 0; | ||
180 | }; | ||
181 | |||
182 | /******************************************************************************* | ||
183 | * Yealink key interface | ||
184 | ******************************************************************************/ | ||
185 | |||
186 | /* Map device buttons to internal key events. | ||
187 | * | ||
188 | * USB-P1K button layout: | ||
189 | * | ||
190 | * up | ||
191 | * IN OUT | ||
192 | * down | ||
193 | * | ||
194 | * pickup C hangup | ||
195 | * 1 2 3 | ||
196 | * 4 5 6 | ||
197 | * 7 8 9 | ||
198 | * * 0 # | ||
199 | * | ||
200 | * The "up" and "down" keys, are symbolised by arrows on the button. | ||
201 | * The "pickup" and "hangup" keys are symbolised by a green and red phone | ||
202 | * on the button. | ||
203 | */ | ||
204 | static int map_p1k_to_key(int scancode) | ||
205 | { | ||
206 | switch(scancode) { /* phone key: */ | ||
207 | case 0x23: return KEY_LEFT; /* IN */ | ||
208 | case 0x33: return KEY_UP; /* up */ | ||
209 | case 0x04: return KEY_RIGHT; /* OUT */ | ||
210 | case 0x24: return KEY_DOWN; /* down */ | ||
211 | case 0x03: return KEY_ENTER; /* pickup */ | ||
212 | case 0x14: return KEY_BACKSPACE; /* C */ | ||
213 | case 0x13: return KEY_ESC; /* hangup */ | ||
214 | case 0x00: return KEY_1; /* 1 */ | ||
215 | case 0x01: return KEY_2; /* 2 */ | ||
216 | case 0x02: return KEY_3; /* 3 */ | ||
217 | case 0x10: return KEY_4; /* 4 */ | ||
218 | case 0x11: return KEY_5; /* 5 */ | ||
219 | case 0x12: return KEY_6; /* 6 */ | ||
220 | case 0x20: return KEY_7; /* 7 */ | ||
221 | case 0x21: return KEY_8; /* 8 */ | ||
222 | case 0x22: return KEY_9; /* 9 */ | ||
223 | case 0x30: return KEY_KPASTERISK; /* * */ | ||
224 | case 0x31: return KEY_0; /* 0 */ | ||
225 | case 0x32: return KEY_LEFTSHIFT | | ||
226 | KEY_3 << 8; /* # */ | ||
227 | } | ||
228 | return -EINVAL; | ||
229 | } | ||
230 | |||
231 | /* Completes a request by converting the data into events for the | ||
232 | * input subsystem. | ||
233 | * | ||
234 | * The key parameter can be cascaded: key2 << 8 | key1 | ||
235 | */ | ||
236 | static void report_key(struct yealink_dev *yld, int key) | ||
237 | { | ||
238 | struct input_dev *idev = yld->idev; | ||
239 | |||
240 | if (yld->key_code >= 0) { | ||
241 | /* old key up */ | ||
242 | input_report_key(idev, yld->key_code & 0xff, 0); | ||
243 | if (yld->key_code >> 8) | ||
244 | input_report_key(idev, yld->key_code >> 8, 0); | ||
245 | } | ||
246 | |||
247 | yld->key_code = key; | ||
248 | if (key >= 0) { | ||
249 | /* new valid key */ | ||
250 | input_report_key(idev, key & 0xff, 1); | ||
251 | if (key >> 8) | ||
252 | input_report_key(idev, key >> 8, 1); | ||
253 | } | ||
254 | input_sync(idev); | ||
255 | } | ||
256 | |||
257 | /******************************************************************************* | ||
258 | * Yealink usb communication interface | ||
259 | ******************************************************************************/ | ||
260 | |||
261 | static int yealink_cmd(struct yealink_dev *yld, struct yld_ctl_packet *p) | ||
262 | { | ||
263 | u8 *buf = (u8 *)p; | ||
264 | int i; | ||
265 | u8 sum = 0; | ||
266 | |||
267 | for(i=0; i<USB_PKT_LEN-1; i++) | ||
268 | sum -= buf[i]; | ||
269 | p->sum = sum; | ||
270 | return usb_control_msg(yld->udev, | ||
271 | usb_sndctrlpipe(yld->udev, 0), | ||
272 | USB_REQ_SET_CONFIGURATION, | ||
273 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
274 | 0x200, 3, | ||
275 | p, sizeof(*p), | ||
276 | USB_CTRL_SET_TIMEOUT); | ||
277 | } | ||
278 | |||
279 | static u8 default_ringtone[] = { | ||
280 | 0xEF, /* volume [0-255] */ | ||
281 | 0xFB, 0x1E, 0x00, 0x0C, /* 1250 [hz], 12/100 [s] */ | ||
282 | 0xFC, 0x18, 0x00, 0x0C, /* 1000 [hz], 12/100 [s] */ | ||
283 | 0xFB, 0x1E, 0x00, 0x0C, | ||
284 | 0xFC, 0x18, 0x00, 0x0C, | ||
285 | 0xFB, 0x1E, 0x00, 0x0C, | ||
286 | 0xFC, 0x18, 0x00, 0x0C, | ||
287 | 0xFB, 0x1E, 0x00, 0x0C, | ||
288 | 0xFC, 0x18, 0x00, 0x0C, | ||
289 | 0xFF, 0xFF, 0x01, 0x90, /* silent, 400/100 [s] */ | ||
290 | 0x00, 0x00 /* end of sequence */ | ||
291 | }; | ||
292 | |||
293 | static int yealink_set_ringtone(struct yealink_dev *yld, u8 *buf, size_t size) | ||
294 | { | ||
295 | struct yld_ctl_packet *p = yld->ctl_data; | ||
296 | int ix, len; | ||
297 | |||
298 | if (size <= 0) | ||
299 | return -EINVAL; | ||
300 | |||
301 | /* Set the ringtone volume */ | ||
302 | memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data))); | ||
303 | yld->ctl_data->cmd = CMD_RING_VOLUME; | ||
304 | yld->ctl_data->size = 1; | ||
305 | yld->ctl_data->data[0] = buf[0]; | ||
306 | yealink_cmd(yld, p); | ||
307 | |||
308 | buf++; | ||
309 | size--; | ||
310 | |||
311 | p->cmd = CMD_RING_NOTE; | ||
312 | ix = 0; | ||
313 | while (size != ix) { | ||
314 | len = size - ix; | ||
315 | if (len > sizeof(p->data)) | ||
316 | len = sizeof(p->data); | ||
317 | p->size = len; | ||
318 | p->offset = cpu_to_be16(ix); | ||
319 | memcpy(p->data, &buf[ix], len); | ||
320 | yealink_cmd(yld, p); | ||
321 | ix += len; | ||
322 | } | ||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | /* keep stat_master & stat_copy in sync. | ||
327 | */ | ||
328 | static int yealink_do_idle_tasks(struct yealink_dev *yld) | ||
329 | { | ||
330 | u8 val; | ||
331 | int i, ix, len; | ||
332 | |||
333 | ix = yld->stat_ix; | ||
334 | |||
335 | memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data))); | ||
336 | yld->ctl_data->cmd = CMD_KEYPRESS; | ||
337 | yld->ctl_data->size = 1; | ||
338 | yld->ctl_data->sum = 0xff - CMD_KEYPRESS; | ||
339 | |||
340 | /* If state update pointer wraps do a KEYPRESS first. */ | ||
341 | if (ix >= sizeof(yld->master)) { | ||
342 | yld->stat_ix = 0; | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | /* find update candidates: copy != master */ | ||
347 | do { | ||
348 | val = yld->master.b[ix]; | ||
349 | if (val != yld->copy.b[ix]) | ||
350 | goto send_update; | ||
351 | } while (++ix < sizeof(yld->master)); | ||
352 | |||
353 | /* nothing todo, wait a bit and poll for a KEYPRESS */ | ||
354 | yld->stat_ix = 0; | ||
355 | /* TODO how can we wait abit. ?? | ||
356 | * msleep_interruptible(1000 / YEALINK_POLLING_FREQUENCY); | ||
357 | */ | ||
358 | return 0; | ||
359 | |||
360 | send_update: | ||
361 | |||
362 | /* Setup an appropriate update request */ | ||
363 | yld->copy.b[ix] = val; | ||
364 | yld->ctl_data->data[0] = val; | ||
365 | |||
366 | switch(ix) { | ||
367 | case offsetof(struct yld_status, led): | ||
368 | yld->ctl_data->cmd = CMD_LED; | ||
369 | yld->ctl_data->sum = -1 - CMD_LED - val; | ||
370 | break; | ||
371 | case offsetof(struct yld_status, dialtone): | ||
372 | yld->ctl_data->cmd = CMD_DIALTONE; | ||
373 | yld->ctl_data->sum = -1 - CMD_DIALTONE - val; | ||
374 | break; | ||
375 | case offsetof(struct yld_status, ringtone): | ||
376 | yld->ctl_data->cmd = CMD_RINGTONE; | ||
377 | yld->ctl_data->sum = -1 - CMD_RINGTONE - val; | ||
378 | break; | ||
379 | case offsetof(struct yld_status, keynum): | ||
380 | val--; | ||
381 | val &= 0x1f; | ||
382 | yld->ctl_data->cmd = CMD_SCANCODE; | ||
383 | yld->ctl_data->offset = cpu_to_be16(val); | ||
384 | yld->ctl_data->data[0] = 0; | ||
385 | yld->ctl_data->sum = -1 - CMD_SCANCODE - val; | ||
386 | break; | ||
387 | default: | ||
388 | len = sizeof(yld->master.s.lcd) - ix; | ||
389 | if (len > sizeof(yld->ctl_data->data)) | ||
390 | len = sizeof(yld->ctl_data->data); | ||
391 | |||
392 | /* Combine up to <len> consecutive LCD bytes in a singe request | ||
393 | */ | ||
394 | yld->ctl_data->cmd = CMD_LCD; | ||
395 | yld->ctl_data->offset = cpu_to_be16(ix); | ||
396 | yld->ctl_data->size = len; | ||
397 | yld->ctl_data->sum = -CMD_LCD - ix - val - len; | ||
398 | for(i=1; i<len; i++) { | ||
399 | ix++; | ||
400 | val = yld->master.b[ix]; | ||
401 | yld->copy.b[ix] = val; | ||
402 | yld->ctl_data->data[i] = val; | ||
403 | yld->ctl_data->sum -= val; | ||
404 | } | ||
405 | } | ||
406 | yld->stat_ix = ix + 1; | ||
407 | return 1; | ||
408 | } | ||
409 | |||
410 | /* Decide on how to handle responses | ||
411 | * | ||
412 | * The state transition diagram is somethhing like: | ||
413 | * | ||
414 | * syncState<--+ | ||
415 | * | | | ||
416 | * | idle | ||
417 | * \|/ | | ||
418 | * init --ok--> waitForKey --ok--> getKey | ||
419 | * ^ ^ | | ||
420 | * | +-------ok-------+ | ||
421 | * error,start | ||
422 | * | ||
423 | */ | ||
424 | static void urb_irq_callback(struct urb *urb) | ||
425 | { | ||
426 | struct yealink_dev *yld = urb->context; | ||
427 | int ret; | ||
428 | |||
429 | if (urb->status) | ||
430 | err("%s - urb status %d", __FUNCTION__, urb->status); | ||
431 | |||
432 | switch (yld->irq_data->cmd) { | ||
433 | case CMD_KEYPRESS: | ||
434 | |||
435 | yld->master.s.keynum = yld->irq_data->data[0]; | ||
436 | break; | ||
437 | |||
438 | case CMD_SCANCODE: | ||
439 | dbg("get scancode %x", yld->irq_data->data[0]); | ||
440 | |||
441 | report_key(yld, map_p1k_to_key(yld->irq_data->data[0])); | ||
442 | break; | ||
443 | |||
444 | default: | ||
445 | err("unexpected response %x", yld->irq_data->cmd); | ||
446 | } | ||
447 | |||
448 | yealink_do_idle_tasks(yld); | ||
449 | |||
450 | ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC); | ||
451 | if (ret) | ||
452 | err("%s - usb_submit_urb failed %d", __FUNCTION__, ret); | ||
453 | } | ||
454 | |||
455 | static void urb_ctl_callback(struct urb *urb) | ||
456 | { | ||
457 | struct yealink_dev *yld = urb->context; | ||
458 | int ret; | ||
459 | |||
460 | if (urb->status) | ||
461 | err("%s - urb status %d", __FUNCTION__, urb->status); | ||
462 | |||
463 | switch (yld->ctl_data->cmd) { | ||
464 | case CMD_KEYPRESS: | ||
465 | case CMD_SCANCODE: | ||
466 | /* ask for a response */ | ||
467 | ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC); | ||
468 | break; | ||
469 | default: | ||
470 | /* send new command */ | ||
471 | yealink_do_idle_tasks(yld); | ||
472 | ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC); | ||
473 | } | ||
474 | |||
475 | if (ret) | ||
476 | err("%s - usb_submit_urb failed %d", __FUNCTION__, ret); | ||
477 | } | ||
478 | |||
479 | /******************************************************************************* | ||
480 | * input event interface | ||
481 | ******************************************************************************/ | ||
482 | |||
483 | /* TODO should we issue a ringtone on a SND_BELL event? | ||
484 | static int input_ev(struct input_dev *dev, unsigned int type, | ||
485 | unsigned int code, int value) | ||
486 | { | ||
487 | |||
488 | if (type != EV_SND) | ||
489 | return -EINVAL; | ||
490 | |||
491 | switch (code) { | ||
492 | case SND_BELL: | ||
493 | case SND_TONE: | ||
494 | break; | ||
495 | default: | ||
496 | return -EINVAL; | ||
497 | } | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | */ | ||
502 | |||
503 | static int input_open(struct input_dev *dev) | ||
504 | { | ||
505 | struct yealink_dev *yld = input_get_drvdata(dev); | ||
506 | int i, ret; | ||
507 | |||
508 | dbg("%s", __FUNCTION__); | ||
509 | |||
510 | /* force updates to device */ | ||
511 | for (i = 0; i<sizeof(yld->master); i++) | ||
512 | yld->copy.b[i] = ~yld->master.b[i]; | ||
513 | yld->key_code = -1; /* no keys pressed */ | ||
514 | |||
515 | yealink_set_ringtone(yld, default_ringtone, sizeof(default_ringtone)); | ||
516 | |||
517 | /* issue INIT */ | ||
518 | memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data))); | ||
519 | yld->ctl_data->cmd = CMD_INIT; | ||
520 | yld->ctl_data->size = 10; | ||
521 | yld->ctl_data->sum = 0x100-CMD_INIT-10; | ||
522 | if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) { | ||
523 | dbg("%s - usb_submit_urb failed with result %d", | ||
524 | __FUNCTION__, ret); | ||
525 | return ret; | ||
526 | } | ||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static void input_close(struct input_dev *dev) | ||
531 | { | ||
532 | struct yealink_dev *yld = input_get_drvdata(dev); | ||
533 | |||
534 | usb_kill_urb(yld->urb_ctl); | ||
535 | usb_kill_urb(yld->urb_irq); | ||
536 | } | ||
537 | |||
538 | /******************************************************************************* | ||
539 | * sysfs interface | ||
540 | ******************************************************************************/ | ||
541 | |||
542 | static DECLARE_RWSEM(sysfs_rwsema); | ||
543 | |||
544 | /* Interface to the 7-segments translation table aka. char set. | ||
545 | */ | ||
546 | static ssize_t show_map(struct device *dev, struct device_attribute *attr, | ||
547 | char *buf) | ||
548 | { | ||
549 | memcpy(buf, &map_seg7, sizeof(map_seg7)); | ||
550 | return sizeof(map_seg7); | ||
551 | } | ||
552 | |||
553 | static ssize_t store_map(struct device *dev, struct device_attribute *attr, | ||
554 | const char *buf, size_t cnt) | ||
555 | { | ||
556 | if (cnt != sizeof(map_seg7)) | ||
557 | return -EINVAL; | ||
558 | memcpy(&map_seg7, buf, sizeof(map_seg7)); | ||
559 | return sizeof(map_seg7); | ||
560 | } | ||
561 | |||
562 | /* Interface to the LCD. | ||
563 | */ | ||
564 | |||
565 | /* Reading /sys/../lineX will return the format string with its settings: | ||
566 | * | ||
567 | * Example: | ||
568 | * cat ./line3 | ||
569 | * 888888888888 | ||
570 | * Linux Rocks! | ||
571 | */ | ||
572 | static ssize_t show_line(struct device *dev, char *buf, int a, int b) | ||
573 | { | ||
574 | struct yealink_dev *yld; | ||
575 | int i; | ||
576 | |||
577 | down_read(&sysfs_rwsema); | ||
578 | yld = dev_get_drvdata(dev); | ||
579 | if (yld == NULL) { | ||
580 | up_read(&sysfs_rwsema); | ||
581 | return -ENODEV; | ||
582 | } | ||
583 | |||
584 | for (i = a; i < b; i++) | ||
585 | *buf++ = lcdMap[i].type; | ||
586 | *buf++ = '\n'; | ||
587 | for (i = a; i < b; i++) | ||
588 | *buf++ = yld->lcdMap[i]; | ||
589 | *buf++ = '\n'; | ||
590 | *buf = 0; | ||
591 | |||
592 | up_read(&sysfs_rwsema); | ||
593 | return 3 + ((b - a) << 1); | ||
594 | } | ||
595 | |||
596 | static ssize_t show_line1(struct device *dev, struct device_attribute *attr, | ||
597 | char *buf) | ||
598 | { | ||
599 | return show_line(dev, buf, LCD_LINE1_OFFSET, LCD_LINE2_OFFSET); | ||
600 | } | ||
601 | |||
602 | static ssize_t show_line2(struct device *dev, struct device_attribute *attr, | ||
603 | char *buf) | ||
604 | { | ||
605 | return show_line(dev, buf, LCD_LINE2_OFFSET, LCD_LINE3_OFFSET); | ||
606 | } | ||
607 | |||
608 | static ssize_t show_line3(struct device *dev, struct device_attribute *attr, | ||
609 | char *buf) | ||
610 | { | ||
611 | return show_line(dev, buf, LCD_LINE3_OFFSET, LCD_LINE4_OFFSET); | ||
612 | } | ||
613 | |||
614 | /* Writing to /sys/../lineX will set the coresponding LCD line. | ||
615 | * - Excess characters are ignored. | ||
616 | * - If less characters are written than allowed, the remaining digits are | ||
617 | * unchanged. | ||
618 | * - The '\n' or '\t' char is a placeholder, it does not overwrite the | ||
619 | * original content. | ||
620 | */ | ||
621 | static ssize_t store_line(struct device *dev, const char *buf, size_t count, | ||
622 | int el, size_t len) | ||
623 | { | ||
624 | struct yealink_dev *yld; | ||
625 | int i; | ||
626 | |||
627 | down_write(&sysfs_rwsema); | ||
628 | yld = dev_get_drvdata(dev); | ||
629 | if (yld == NULL) { | ||
630 | up_write(&sysfs_rwsema); | ||
631 | return -ENODEV; | ||
632 | } | ||
633 | |||
634 | if (len > count) | ||
635 | len = count; | ||
636 | for (i = 0; i < len; i++) | ||
637 | setChar(yld, el++, buf[i]); | ||
638 | |||
639 | up_write(&sysfs_rwsema); | ||
640 | return count; | ||
641 | } | ||
642 | |||
643 | static ssize_t store_line1(struct device *dev, struct device_attribute *attr, | ||
644 | const char *buf, size_t count) | ||
645 | { | ||
646 | return store_line(dev, buf, count, LCD_LINE1_OFFSET, LCD_LINE1_SIZE); | ||
647 | } | ||
648 | |||
649 | static ssize_t store_line2(struct device *dev, struct device_attribute *attr, | ||
650 | const char *buf, size_t count) | ||
651 | { | ||
652 | return store_line(dev, buf, count, LCD_LINE2_OFFSET, LCD_LINE2_SIZE); | ||
653 | } | ||
654 | |||
655 | static ssize_t store_line3(struct device *dev, struct device_attribute *attr, | ||
656 | const char *buf, size_t count) | ||
657 | { | ||
658 | return store_line(dev, buf, count, LCD_LINE3_OFFSET, LCD_LINE3_SIZE); | ||
659 | } | ||
660 | |||
661 | /* Interface to visible and audible "icons", these include: | ||
662 | * pictures on the LCD, the LED, and the dialtone signal. | ||
663 | */ | ||
664 | |||
665 | /* Get a list of "switchable elements" with their current state. */ | ||
666 | static ssize_t get_icons(struct device *dev, struct device_attribute *attr, | ||
667 | char *buf) | ||
668 | { | ||
669 | struct yealink_dev *yld; | ||
670 | int i, ret = 1; | ||
671 | |||
672 | down_read(&sysfs_rwsema); | ||
673 | yld = dev_get_drvdata(dev); | ||
674 | if (yld == NULL) { | ||
675 | up_read(&sysfs_rwsema); | ||
676 | return -ENODEV; | ||
677 | } | ||
678 | |||
679 | for (i = 0; i < ARRAY_SIZE(lcdMap); i++) { | ||
680 | if (lcdMap[i].type != '.') | ||
681 | continue; | ||
682 | ret += sprintf(&buf[ret], "%s %s\n", | ||
683 | yld->lcdMap[i] == ' ' ? " " : "on", | ||
684 | lcdMap[i].u.p.name); | ||
685 | } | ||
686 | up_read(&sysfs_rwsema); | ||
687 | return ret; | ||
688 | } | ||
689 | |||
690 | /* Change the visibility of a particular element. */ | ||
691 | static ssize_t set_icon(struct device *dev, const char *buf, size_t count, | ||
692 | int chr) | ||
693 | { | ||
694 | struct yealink_dev *yld; | ||
695 | int i; | ||
696 | |||
697 | down_write(&sysfs_rwsema); | ||
698 | yld = dev_get_drvdata(dev); | ||
699 | if (yld == NULL) { | ||
700 | up_write(&sysfs_rwsema); | ||
701 | return -ENODEV; | ||
702 | } | ||
703 | |||
704 | for (i = 0; i < ARRAY_SIZE(lcdMap); i++) { | ||
705 | if (lcdMap[i].type != '.') | ||
706 | continue; | ||
707 | if (strncmp(buf, lcdMap[i].u.p.name, count) == 0) { | ||
708 | setChar(yld, i, chr); | ||
709 | break; | ||
710 | } | ||
711 | } | ||
712 | |||
713 | up_write(&sysfs_rwsema); | ||
714 | return count; | ||
715 | } | ||
716 | |||
717 | static ssize_t show_icon(struct device *dev, struct device_attribute *attr, | ||
718 | const char *buf, size_t count) | ||
719 | { | ||
720 | return set_icon(dev, buf, count, buf[0]); | ||
721 | } | ||
722 | |||
723 | static ssize_t hide_icon(struct device *dev, struct device_attribute *attr, | ||
724 | const char *buf, size_t count) | ||
725 | { | ||
726 | return set_icon(dev, buf, count, ' '); | ||
727 | } | ||
728 | |||
729 | /* Upload a ringtone to the device. | ||
730 | */ | ||
731 | |||
732 | /* Stores raw ringtone data in the phone */ | ||
733 | static ssize_t store_ringtone(struct device *dev, | ||
734 | struct device_attribute *attr, | ||
735 | const char *buf, size_t count) | ||
736 | { | ||
737 | struct yealink_dev *yld; | ||
738 | |||
739 | down_write(&sysfs_rwsema); | ||
740 | yld = dev_get_drvdata(dev); | ||
741 | if (yld == NULL) { | ||
742 | up_write(&sysfs_rwsema); | ||
743 | return -ENODEV; | ||
744 | } | ||
745 | |||
746 | /* TODO locking with async usb control interface??? */ | ||
747 | yealink_set_ringtone(yld, (char *)buf, count); | ||
748 | up_write(&sysfs_rwsema); | ||
749 | return count; | ||
750 | } | ||
751 | |||
752 | #define _M444 S_IRUGO | ||
753 | #define _M664 S_IRUGO|S_IWUSR|S_IWGRP | ||
754 | #define _M220 S_IWUSR|S_IWGRP | ||
755 | |||
756 | static DEVICE_ATTR(map_seg7 , _M664, show_map , store_map ); | ||
757 | static DEVICE_ATTR(line1 , _M664, show_line1 , store_line1 ); | ||
758 | static DEVICE_ATTR(line2 , _M664, show_line2 , store_line2 ); | ||
759 | static DEVICE_ATTR(line3 , _M664, show_line3 , store_line3 ); | ||
760 | static DEVICE_ATTR(get_icons , _M444, get_icons , NULL ); | ||
761 | static DEVICE_ATTR(show_icon , _M220, NULL , show_icon ); | ||
762 | static DEVICE_ATTR(hide_icon , _M220, NULL , hide_icon ); | ||
763 | static DEVICE_ATTR(ringtone , _M220, NULL , store_ringtone); | ||
764 | |||
765 | static struct attribute *yld_attributes[] = { | ||
766 | &dev_attr_line1.attr, | ||
767 | &dev_attr_line2.attr, | ||
768 | &dev_attr_line3.attr, | ||
769 | &dev_attr_get_icons.attr, | ||
770 | &dev_attr_show_icon.attr, | ||
771 | &dev_attr_hide_icon.attr, | ||
772 | &dev_attr_map_seg7.attr, | ||
773 | &dev_attr_ringtone.attr, | ||
774 | NULL | ||
775 | }; | ||
776 | |||
777 | static struct attribute_group yld_attr_group = { | ||
778 | .attrs = yld_attributes | ||
779 | }; | ||
780 | |||
781 | /******************************************************************************* | ||
782 | * Linux interface and usb initialisation | ||
783 | ******************************************************************************/ | ||
784 | |||
785 | struct driver_info { | ||
786 | char *name; | ||
787 | }; | ||
788 | |||
789 | static const struct driver_info info_P1K = { | ||
790 | .name = "Yealink usb-p1k", | ||
791 | }; | ||
792 | |||
793 | static const struct usb_device_id usb_table [] = { | ||
794 | { | ||
795 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | | ||
796 | USB_DEVICE_ID_MATCH_INT_INFO, | ||
797 | .idVendor = 0x6993, | ||
798 | .idProduct = 0xb001, | ||
799 | .bInterfaceClass = USB_CLASS_HID, | ||
800 | .bInterfaceSubClass = 0, | ||
801 | .bInterfaceProtocol = 0, | ||
802 | .driver_info = (kernel_ulong_t)&info_P1K | ||
803 | }, | ||
804 | { } | ||
805 | }; | ||
806 | |||
807 | static int usb_cleanup(struct yealink_dev *yld, int err) | ||
808 | { | ||
809 | if (yld == NULL) | ||
810 | return err; | ||
811 | |||
812 | usb_kill_urb(yld->urb_irq); /* parameter validation in core/urb */ | ||
813 | usb_kill_urb(yld->urb_ctl); /* parameter validation in core/urb */ | ||
814 | |||
815 | if (yld->idev) { | ||
816 | if (err) | ||
817 | input_free_device(yld->idev); | ||
818 | else | ||
819 | input_unregister_device(yld->idev); | ||
820 | } | ||
821 | |||
822 | usb_free_urb(yld->urb_irq); | ||
823 | usb_free_urb(yld->urb_ctl); | ||
824 | |||
825 | usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)), | ||
826 | yld->ctl_req, yld->ctl_req_dma); | ||
827 | usb_buffer_free(yld->udev, USB_PKT_LEN, | ||
828 | yld->ctl_data, yld->ctl_dma); | ||
829 | usb_buffer_free(yld->udev, USB_PKT_LEN, | ||
830 | yld->irq_data, yld->irq_dma); | ||
831 | |||
832 | kfree(yld); | ||
833 | return err; | ||
834 | } | ||
835 | |||
836 | static void usb_disconnect(struct usb_interface *intf) | ||
837 | { | ||
838 | struct yealink_dev *yld; | ||
839 | |||
840 | down_write(&sysfs_rwsema); | ||
841 | yld = usb_get_intfdata(intf); | ||
842 | sysfs_remove_group(&intf->dev.kobj, &yld_attr_group); | ||
843 | usb_set_intfdata(intf, NULL); | ||
844 | up_write(&sysfs_rwsema); | ||
845 | |||
846 | usb_cleanup(yld, 0); | ||
847 | } | ||
848 | |||
849 | static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
850 | { | ||
851 | struct usb_device *udev = interface_to_usbdev (intf); | ||
852 | struct driver_info *nfo = (struct driver_info *)id->driver_info; | ||
853 | struct usb_host_interface *interface; | ||
854 | struct usb_endpoint_descriptor *endpoint; | ||
855 | struct yealink_dev *yld; | ||
856 | struct input_dev *input_dev; | ||
857 | int ret, pipe, i; | ||
858 | |||
859 | interface = intf->cur_altsetting; | ||
860 | endpoint = &interface->endpoint[0].desc; | ||
861 | if (!usb_endpoint_is_int_in(endpoint)) | ||
862 | return -ENODEV; | ||
863 | |||
864 | yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL); | ||
865 | if (!yld) | ||
866 | return -ENOMEM; | ||
867 | |||
868 | yld->udev = udev; | ||
869 | |||
870 | yld->idev = input_dev = input_allocate_device(); | ||
871 | if (!input_dev) | ||
872 | return usb_cleanup(yld, -ENOMEM); | ||
873 | |||
874 | /* allocate usb buffers */ | ||
875 | yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, | ||
876 | GFP_ATOMIC, &yld->irq_dma); | ||
877 | if (yld->irq_data == NULL) | ||
878 | return usb_cleanup(yld, -ENOMEM); | ||
879 | |||
880 | yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, | ||
881 | GFP_ATOMIC, &yld->ctl_dma); | ||
882 | if (!yld->ctl_data) | ||
883 | return usb_cleanup(yld, -ENOMEM); | ||
884 | |||
885 | yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)), | ||
886 | GFP_ATOMIC, &yld->ctl_req_dma); | ||
887 | if (yld->ctl_req == NULL) | ||
888 | return usb_cleanup(yld, -ENOMEM); | ||
889 | |||
890 | /* allocate urb structures */ | ||
891 | yld->urb_irq = usb_alloc_urb(0, GFP_KERNEL); | ||
892 | if (yld->urb_irq == NULL) | ||
893 | return usb_cleanup(yld, -ENOMEM); | ||
894 | |||
895 | yld->urb_ctl = usb_alloc_urb(0, GFP_KERNEL); | ||
896 | if (yld->urb_ctl == NULL) | ||
897 | return usb_cleanup(yld, -ENOMEM); | ||
898 | |||
899 | /* get a handle to the interrupt data pipe */ | ||
900 | pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); | ||
901 | ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
902 | if (ret != USB_PKT_LEN) | ||
903 | err("invalid payload size %d, expected %zd", ret, USB_PKT_LEN); | ||
904 | |||
905 | /* initialise irq urb */ | ||
906 | usb_fill_int_urb(yld->urb_irq, udev, pipe, yld->irq_data, | ||
907 | USB_PKT_LEN, | ||
908 | urb_irq_callback, | ||
909 | yld, endpoint->bInterval); | ||
910 | yld->urb_irq->transfer_dma = yld->irq_dma; | ||
911 | yld->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
912 | yld->urb_irq->dev = udev; | ||
913 | |||
914 | /* initialise ctl urb */ | ||
915 | yld->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
916 | USB_DIR_OUT; | ||
917 | yld->ctl_req->bRequest = USB_REQ_SET_CONFIGURATION; | ||
918 | yld->ctl_req->wValue = cpu_to_le16(0x200); | ||
919 | yld->ctl_req->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); | ||
920 | yld->ctl_req->wLength = cpu_to_le16(USB_PKT_LEN); | ||
921 | |||
922 | usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0), | ||
923 | (void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN, | ||
924 | urb_ctl_callback, yld); | ||
925 | yld->urb_ctl->setup_dma = yld->ctl_req_dma; | ||
926 | yld->urb_ctl->transfer_dma = yld->ctl_dma; | ||
927 | yld->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP | | ||
928 | URB_NO_TRANSFER_DMA_MAP; | ||
929 | yld->urb_ctl->dev = udev; | ||
930 | |||
931 | /* find out the physical bus location */ | ||
932 | usb_make_path(udev, yld->phys, sizeof(yld->phys)); | ||
933 | strlcat(yld->phys, "/input0", sizeof(yld->phys)); | ||
934 | |||
935 | /* register settings for the input device */ | ||
936 | input_dev->name = nfo->name; | ||
937 | input_dev->phys = yld->phys; | ||
938 | usb_to_input_id(udev, &input_dev->id); | ||
939 | input_dev->dev.parent = &intf->dev; | ||
940 | |||
941 | input_set_drvdata(input_dev, yld); | ||
942 | |||
943 | input_dev->open = input_open; | ||
944 | input_dev->close = input_close; | ||
945 | /* input_dev->event = input_ev; TODO */ | ||
946 | |||
947 | /* register available key events */ | ||
948 | input_dev->evbit[0] = BIT(EV_KEY); | ||
949 | for (i = 0; i < 256; i++) { | ||
950 | int k = map_p1k_to_key(i); | ||
951 | if (k >= 0) { | ||
952 | set_bit(k & 0xff, input_dev->keybit); | ||
953 | if (k >> 8) | ||
954 | set_bit(k >> 8, input_dev->keybit); | ||
955 | } | ||
956 | } | ||
957 | |||
958 | ret = input_register_device(yld->idev); | ||
959 | if (ret) | ||
960 | return usb_cleanup(yld, ret); | ||
961 | |||
962 | usb_set_intfdata(intf, yld); | ||
963 | |||
964 | /* clear visible elements */ | ||
965 | for (i = 0; i < ARRAY_SIZE(lcdMap); i++) | ||
966 | setChar(yld, i, ' '); | ||
967 | |||
968 | /* display driver version on LCD line 3 */ | ||
969 | store_line3(&intf->dev, NULL, | ||
970 | DRIVER_VERSION, sizeof(DRIVER_VERSION)); | ||
971 | |||
972 | /* Register sysfs hooks (don't care about failure) */ | ||
973 | ret = sysfs_create_group(&intf->dev.kobj, &yld_attr_group); | ||
974 | return 0; | ||
975 | } | ||
976 | |||
977 | static struct usb_driver yealink_driver = { | ||
978 | .name = "yealink", | ||
979 | .probe = usb_probe, | ||
980 | .disconnect = usb_disconnect, | ||
981 | .id_table = usb_table, | ||
982 | }; | ||
983 | |||
984 | static int __init yealink_dev_init(void) | ||
985 | { | ||
986 | int ret = usb_register(&yealink_driver); | ||
987 | if (ret == 0) | ||
988 | info(DRIVER_DESC ":" DRIVER_VERSION); | ||
989 | return ret; | ||
990 | } | ||
991 | |||
992 | static void __exit yealink_dev_exit(void) | ||
993 | { | ||
994 | usb_deregister(&yealink_driver); | ||
995 | } | ||
996 | |||
997 | module_init(yealink_dev_init); | ||
998 | module_exit(yealink_dev_exit); | ||
999 | |||
1000 | MODULE_DEVICE_TABLE (usb, usb_table); | ||
1001 | |||
1002 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1003 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1004 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/yealink.h b/drivers/input/misc/yealink.h new file mode 100644 index 000000000000..48af0be9cbdf --- /dev/null +++ b/drivers/input/misc/yealink.h | |||
@@ -0,0 +1,220 @@ | |||
1 | /* | ||
2 | * drivers/usb/input/yealink.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com> | ||
5 | * | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | #ifndef INPUT_YEALINK_H | ||
22 | #define INPUT_YEALINK_H | ||
23 | |||
24 | /* Using the control channel on interface 3 various aspects of the phone | ||
25 | * can be controlled like LCD, LED, dialtone and the ringtone. | ||
26 | */ | ||
27 | |||
28 | struct yld_ctl_packet { | ||
29 | u8 cmd; /* command code, see below */ | ||
30 | u8 size; /* 1-11, size of used data bytes. */ | ||
31 | u16 offset; /* internal packet offset */ | ||
32 | u8 data[11]; | ||
33 | s8 sum; /* negative sum of 15 preceding bytes */ | ||
34 | } __attribute__ ((packed)); | ||
35 | |||
36 | #define USB_PKT_LEN sizeof(struct yld_ctl_packet) | ||
37 | |||
38 | /* The following yld_ctl_packet's are available: */ | ||
39 | |||
40 | /* Init registers | ||
41 | * | ||
42 | * cmd 0x8e | ||
43 | * size 10 | ||
44 | * offset 0 | ||
45 | * data 0,0,0,0.... | ||
46 | */ | ||
47 | #define CMD_INIT 0x8e | ||
48 | |||
49 | /* Request key scan | ||
50 | * | ||
51 | * cmd 0x80 | ||
52 | * size 1 | ||
53 | * offset 0 | ||
54 | * data[0] on return returns the key number, if it changes there's a new | ||
55 | * key pressed. | ||
56 | */ | ||
57 | #define CMD_KEYPRESS 0x80 | ||
58 | |||
59 | /* Request scancode | ||
60 | * | ||
61 | * cmd 0x81 | ||
62 | * size 1 | ||
63 | * offset key number [0-1f] | ||
64 | * data[0] on return returns the scancode | ||
65 | */ | ||
66 | #define CMD_SCANCODE 0x81 | ||
67 | |||
68 | /* Set LCD | ||
69 | * | ||
70 | * cmd 0x04 | ||
71 | * size 1-11 | ||
72 | * offset 0-23 | ||
73 | * data segment bits | ||
74 | */ | ||
75 | #define CMD_LCD 0x04 | ||
76 | |||
77 | /* Set led | ||
78 | * | ||
79 | * cmd 0x05 | ||
80 | * size 1 | ||
81 | * offset 0 | ||
82 | * data[0] 0 OFF / 1 ON | ||
83 | */ | ||
84 | #define CMD_LED 0x05 | ||
85 | |||
86 | /* Set ringtone volume | ||
87 | * | ||
88 | * cmd 0x11 | ||
89 | * size 1 | ||
90 | * offset 0 | ||
91 | * data[0] 0-0xff volume | ||
92 | */ | ||
93 | #define CMD_RING_VOLUME 0x11 | ||
94 | |||
95 | /* Set ringtone notes | ||
96 | * | ||
97 | * cmd 0x02 | ||
98 | * size 1-11 | ||
99 | * offset 0-> | ||
100 | * data binary representation LE16(-freq), LE16(duration) .... | ||
101 | */ | ||
102 | #define CMD_RING_NOTE 0x02 | ||
103 | |||
104 | /* Sound ringtone via the speaker on the back | ||
105 | * | ||
106 | * cmd 0x03 | ||
107 | * size 1 | ||
108 | * offset 0 | ||
109 | * data[0] 0 OFF / 0x24 ON | ||
110 | */ | ||
111 | #define CMD_RINGTONE 0x03 | ||
112 | |||
113 | /* Sound dial tone via the ear speaker | ||
114 | * | ||
115 | * cmd 0x09 | ||
116 | * size 1 | ||
117 | * offset 0 | ||
118 | * data[0] 0 OFF / 1 ON | ||
119 | */ | ||
120 | #define CMD_DIALTONE 0x09 | ||
121 | |||
122 | #endif /* INPUT_YEALINK_H */ | ||
123 | |||
124 | |||
125 | #if defined(_SEG) && defined(_PIC) | ||
126 | /* This table maps the LCD segments onto individual bit positions in the | ||
127 | * yld_status struct. | ||
128 | */ | ||
129 | |||
130 | /* LCD, each segment must be driven seperately. | ||
131 | * | ||
132 | * Layout: | ||
133 | * | ||
134 | * |[] [][] [][] [][] in |[][] | ||
135 | * |[] M [][] D [][] : [][] out |[][] | ||
136 | * store | ||
137 | * | ||
138 | * NEW REP SU MO TU WE TH FR SA | ||
139 | * | ||
140 | * [] [] [] [] [] [] [] [] [] [] [] [] | ||
141 | * [] [] [] [] [] [] [] [] [] [] [] [] | ||
142 | */ | ||
143 | |||
144 | /* Line 1 | ||
145 | * Format : 18.e8.M8.88...188 | ||
146 | * Icon names : M D : IN OUT STORE | ||
147 | */ | ||
148 | #define LCD_LINE1_OFFSET 0 | ||
149 | #define LCD_LINE1_SIZE 17 | ||
150 | |||
151 | /* Note: first g then f => ! ! */ | ||
152 | /* _SEG( type a b c d e g f ) */ | ||
153 | _SEG('1', 0,0 , 22,2 , 22,2 , 0,0 , 0,0 , 0,0 , 0,0 ), | ||
154 | _SEG('8', 20,1 , 20,2 , 20,4 , 20,8 , 21,4 , 21,2 , 21,1 ), | ||
155 | _PIC('.', 22,1 , "M" ), | ||
156 | _SEG('e', 18,1 , 18,2 , 18,4 , 18,1 , 19,2 , 18,1 , 19,1 ), | ||
157 | _SEG('8', 16,1 , 16,2 , 16,4 , 16,8 , 17,4 , 17,2 , 17,1 ), | ||
158 | _PIC('.', 15,8 , "D" ), | ||
159 | _SEG('M', 14,1 , 14,2 , 14,4 , 14,1 , 15,4 , 15,2 , 15,1 ), | ||
160 | _SEG('8', 12,1 , 12,2 , 12,4 , 12,8 , 13,4 , 13,2 , 13,1 ), | ||
161 | _PIC('.', 11,8 , ":" ), | ||
162 | _SEG('8', 10,1 , 10,2 , 10,4 , 10,8 , 11,4 , 11,2 , 11,1 ), | ||
163 | _SEG('8', 8,1 , 8,2 , 8,4 , 8,8 , 9,4 , 9,2 , 9,1 ), | ||
164 | _PIC('.', 7,1 , "IN" ), | ||
165 | _PIC('.', 7,2 , "OUT" ), | ||
166 | _PIC('.', 7,4 , "STORE" ), | ||
167 | _SEG('1', 0,0 , 5,1 , 5,1 , 0,0 , 0,0 , 0,0 , 0,0 ), | ||
168 | _SEG('8', 4,1 , 4,2 , 4,4 , 4,8 , 5,8 , 5,4 , 5,2 ), | ||
169 | _SEG('8', 2,1 , 2,2 , 2,4 , 2,8 , 3,4 , 3,2 , 3,1 ), | ||
170 | |||
171 | /* Line 2 | ||
172 | * Format : ......... | ||
173 | * Pict. name : NEW REP SU MO TU WE TH FR SA | ||
174 | */ | ||
175 | #define LCD_LINE2_OFFSET LCD_LINE1_OFFSET + LCD_LINE1_SIZE | ||
176 | #define LCD_LINE2_SIZE 9 | ||
177 | |||
178 | _PIC('.', 23,2 , "NEW" ), | ||
179 | _PIC('.', 23,4 , "REP" ), | ||
180 | _PIC('.', 1,8 , "SU" ), | ||
181 | _PIC('.', 1,4 , "MO" ), | ||
182 | _PIC('.', 1,2 , "TU" ), | ||
183 | _PIC('.', 1,1 , "WE" ), | ||
184 | _PIC('.', 0,1 , "TH" ), | ||
185 | _PIC('.', 0,2 , "FR" ), | ||
186 | _PIC('.', 0,4 , "SA" ), | ||
187 | |||
188 | /* Line 3 | ||
189 | * Format : 888888888888 | ||
190 | */ | ||
191 | #define LCD_LINE3_OFFSET LCD_LINE2_OFFSET + LCD_LINE2_SIZE | ||
192 | #define LCD_LINE3_SIZE 12 | ||
193 | |||
194 | _SEG('8', 22,16, 22,32, 22,64, 22,128, 23,128, 23,64, 23,32 ), | ||
195 | _SEG('8', 20,16, 20,32, 20,64, 20,128, 21,128, 21,64, 21,32 ), | ||
196 | _SEG('8', 18,16, 18,32, 18,64, 18,128, 19,128, 19,64, 19,32 ), | ||
197 | _SEG('8', 16,16, 16,32, 16,64, 16,128, 17,128, 17,64, 17,32 ), | ||
198 | _SEG('8', 14,16, 14,32, 14,64, 14,128, 15,128, 15,64, 15,32 ), | ||
199 | _SEG('8', 12,16, 12,32, 12,64, 12,128, 13,128, 13,64, 13,32 ), | ||
200 | _SEG('8', 10,16, 10,32, 10,64, 10,128, 11,128, 11,64, 11,32 ), | ||
201 | _SEG('8', 8,16, 8,32, 8,64, 8,128, 9,128, 9,64, 9,32 ), | ||
202 | _SEG('8', 6,16, 6,32, 6,64, 6,128, 7,128, 7,64, 7,32 ), | ||
203 | _SEG('8', 4,16, 4,32, 4,64, 4,128, 5,128, 5,64, 5,32 ), | ||
204 | _SEG('8', 2,16, 2,32, 2,64, 2,128, 3,128, 3,64, 3,32 ), | ||
205 | _SEG('8', 0,16, 0,32, 0,64, 0,128, 1,128, 1,64, 1,32 ), | ||
206 | |||
207 | /* Line 4 | ||
208 | * | ||
209 | * The LED, DIALTONE and RINGTONE are implemented as icons and use the same | ||
210 | * sysfs interface. | ||
211 | */ | ||
212 | #define LCD_LINE4_OFFSET LCD_LINE3_OFFSET + LCD_LINE3_SIZE | ||
213 | |||
214 | _PIC('.', offsetof(struct yld_status, led) , 0x01, "LED" ), | ||
215 | _PIC('.', offsetof(struct yld_status, dialtone) , 0x01, "DIALTONE" ), | ||
216 | _PIC('.', offsetof(struct yld_status, ringtone) , 0x24, "RINGTONE" ), | ||
217 | |||
218 | #undef _SEG | ||
219 | #undef _PIC | ||
220 | #endif /* _SEG && _PIC */ | ||
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 81dd8c7211a7..2ccc114b3ff6 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -2,7 +2,7 @@ | |||
2 | # Mouse driver configuration | 2 | # Mouse driver configuration |
3 | # | 3 | # |
4 | menuconfig INPUT_MOUSE | 4 | menuconfig INPUT_MOUSE |
5 | bool "Mouse" | 5 | bool "Mice" |
6 | default y | 6 | default y |
7 | help | 7 | help |
8 | Say Y here, and a list of supported mice will be displayed. | 8 | Say Y here, and a list of supported mice will be displayed. |
@@ -19,7 +19,7 @@ config MOUSE_PS2 | |||
19 | select SERIO_LIBPS2 | 19 | select SERIO_LIBPS2 |
20 | select SERIO_I8042 if X86_PC | 20 | select SERIO_I8042 if X86_PC |
21 | select SERIO_GSCPS2 if GSC | 21 | select SERIO_GSCPS2 if GSC |
22 | ---help--- | 22 | help |
23 | Say Y here if you have a PS/2 mouse connected to your system. This | 23 | Say Y here if you have a PS/2 mouse connected to your system. This |
24 | includes the standard 2 or 3-button PS/2 mouse, as well as PS/2 | 24 | includes the standard 2 or 3-button PS/2 mouse, as well as PS/2 |
25 | mice with wheels and extra buttons, Microsoft, Logitech or Genius | 25 | mice with wheels and extra buttons, Microsoft, Logitech or Genius |
@@ -41,7 +41,7 @@ config MOUSE_PS2_ALPS | |||
41 | bool "ALPS PS/2 mouse protocol extension" if EMBEDDED | 41 | bool "ALPS PS/2 mouse protocol extension" if EMBEDDED |
42 | default y | 42 | default y |
43 | depends on MOUSE_PS2 | 43 | depends on MOUSE_PS2 |
44 | ---help--- | 44 | help |
45 | Say Y here if you have an ALPS PS/2 touchpad connected to | 45 | Say Y here if you have an ALPS PS/2 touchpad connected to |
46 | your system. | 46 | your system. |
47 | 47 | ||
@@ -51,7 +51,7 @@ config MOUSE_PS2_LOGIPS2PP | |||
51 | bool "Logictech PS/2++ mouse protocol extension" if EMBEDDED | 51 | bool "Logictech PS/2++ mouse protocol extension" if EMBEDDED |
52 | default y | 52 | default y |
53 | depends on MOUSE_PS2 | 53 | depends on MOUSE_PS2 |
54 | ---help--- | 54 | help |
55 | Say Y here if you have a Logictech PS/2++ mouse connected to | 55 | Say Y here if you have a Logictech PS/2++ mouse connected to |
56 | your system. | 56 | your system. |
57 | 57 | ||
@@ -61,7 +61,7 @@ config MOUSE_PS2_SYNAPTICS | |||
61 | bool "Synaptics PS/2 mouse protocol extension" if EMBEDDED | 61 | bool "Synaptics PS/2 mouse protocol extension" if EMBEDDED |
62 | default y | 62 | default y |
63 | depends on MOUSE_PS2 | 63 | depends on MOUSE_PS2 |
64 | ---help--- | 64 | help |
65 | Say Y here if you have a Synaptics PS/2 TouchPad connected to | 65 | Say Y here if you have a Synaptics PS/2 TouchPad connected to |
66 | your system. | 66 | your system. |
67 | 67 | ||
@@ -71,7 +71,7 @@ config MOUSE_PS2_LIFEBOOK | |||
71 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED | 71 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED |
72 | default y | 72 | default y |
73 | depends on MOUSE_PS2 | 73 | depends on MOUSE_PS2 |
74 | ---help--- | 74 | help |
75 | Say Y here if you have a Fujitsu B-series Lifebook PS/2 | 75 | Say Y here if you have a Fujitsu B-series Lifebook PS/2 |
76 | TouchScreen connected to your system. | 76 | TouchScreen connected to your system. |
77 | 77 | ||
@@ -81,7 +81,7 @@ config MOUSE_PS2_TRACKPOINT | |||
81 | bool "IBM Trackpoint PS/2 mouse protocol extension" if EMBEDDED | 81 | bool "IBM Trackpoint PS/2 mouse protocol extension" if EMBEDDED |
82 | default y | 82 | default y |
83 | depends on MOUSE_PS2 | 83 | depends on MOUSE_PS2 |
84 | ---help--- | 84 | help |
85 | Say Y here if you have an IBM Trackpoint PS/2 mouse connected | 85 | Say Y here if you have an IBM Trackpoint PS/2 mouse connected |
86 | to your system. | 86 | to your system. |
87 | 87 | ||
@@ -90,7 +90,7 @@ config MOUSE_PS2_TRACKPOINT | |||
90 | config MOUSE_PS2_TOUCHKIT | 90 | config MOUSE_PS2_TOUCHKIT |
91 | bool "eGalax TouchKit PS/2 protocol extension" | 91 | bool "eGalax TouchKit PS/2 protocol extension" |
92 | depends on MOUSE_PS2 | 92 | depends on MOUSE_PS2 |
93 | ---help--- | 93 | help |
94 | Say Y here if you have an eGalax TouchKit PS/2 touchscreen | 94 | Say Y here if you have an eGalax TouchKit PS/2 touchscreen |
95 | connected to your system. | 95 | connected to your system. |
96 | 96 | ||
@@ -99,7 +99,7 @@ config MOUSE_PS2_TOUCHKIT | |||
99 | config MOUSE_SERIAL | 99 | config MOUSE_SERIAL |
100 | tristate "Serial mouse" | 100 | tristate "Serial mouse" |
101 | select SERIO | 101 | select SERIO |
102 | ---help--- | 102 | help |
103 | Say Y here if you have a serial (RS-232, COM port) mouse connected | 103 | Say Y here if you have a serial (RS-232, COM port) mouse connected |
104 | to your system. This includes Sun, MouseSystems, Microsoft, | 104 | to your system. This includes Sun, MouseSystems, Microsoft, |
105 | Logitech and all other compatible serial mice. | 105 | Logitech and all other compatible serial mice. |
@@ -109,6 +109,26 @@ config MOUSE_SERIAL | |||
109 | To compile this driver as a module, choose M here: the | 109 | To compile this driver as a module, choose M here: the |
110 | module will be called sermouse. | 110 | module will be called sermouse. |
111 | 111 | ||
112 | config MOUSE_APPLETOUCH | ||
113 | tristate "Apple USB Touchpad support" | ||
114 | select USB | ||
115 | help | ||
116 | Say Y here if you want to use an Apple USB Touchpad. | ||
117 | |||
118 | These are the touchpads that can be found on post-February 2005 | ||
119 | Apple Powerbooks (prior models have a Synaptics touchpad connected | ||
120 | to the ADB bus). | ||
121 | |||
122 | This driver provides a basic mouse driver but can be interfaced | ||
123 | with the synaptics X11 driver to provide acceleration and | ||
124 | scrolling in X11. | ||
125 | |||
126 | For further information, see | ||
127 | <file:Documentation/input/appletouch.txt>. | ||
128 | |||
129 | To compile this driver as a module, choose M here: the | ||
130 | module will be called appletouch. | ||
131 | |||
112 | config MOUSE_INPORT | 132 | config MOUSE_INPORT |
113 | tristate "InPort/MS/ATIXL busmouse" | 133 | tristate "InPort/MS/ATIXL busmouse" |
114 | depends on ISA | 134 | depends on ISA |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 6a8f622927f2..aa4ba878533f 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o | 7 | obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o |
8 | obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o | ||
8 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o | 9 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o |
9 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o | 10 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o |
10 | obj-$(CONFIG_MOUSE_INPORT) += inport.o | 11 | obj-$(CONFIG_MOUSE_INPORT) += inport.o |
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c new file mode 100644 index 000000000000..e3215267db11 --- /dev/null +++ b/drivers/input/mouse/appletouch.c | |||
@@ -0,0 +1,706 @@ | |||
1 | /* | ||
2 | * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver | ||
3 | * | ||
4 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | ||
5 | * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) | ||
6 | * Copyright (C) 2005 Stelian Pop (stelian@popies.net) | ||
7 | * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) | ||
8 | * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) | ||
9 | * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) | ||
10 | * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) | ||
11 | * | ||
12 | * Thanks to Alex Harper <basilisk@foobox.net> for his inputs. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/errno.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/usb/input.h> | ||
36 | |||
37 | /* Apple has powerbooks which have the keyboard with different Product IDs */ | ||
38 | #define APPLE_VENDOR_ID 0x05AC | ||
39 | |||
40 | /* These names come from Info.plist in AppleUSBTrackpad.kext */ | ||
41 | #define FOUNTAIN_ANSI_PRODUCT_ID 0x020E | ||
42 | #define FOUNTAIN_ISO_PRODUCT_ID 0x020F | ||
43 | |||
44 | #define FOUNTAIN_TP_ONLY_PRODUCT_ID 0x030A | ||
45 | |||
46 | #define GEYSER1_TP_ONLY_PRODUCT_ID 0x030B | ||
47 | |||
48 | #define GEYSER_ANSI_PRODUCT_ID 0x0214 | ||
49 | #define GEYSER_ISO_PRODUCT_ID 0x0215 | ||
50 | #define GEYSER_JIS_PRODUCT_ID 0x0216 | ||
51 | |||
52 | /* MacBook devices */ | ||
53 | #define GEYSER3_ANSI_PRODUCT_ID 0x0217 | ||
54 | #define GEYSER3_ISO_PRODUCT_ID 0x0218 | ||
55 | #define GEYSER3_JIS_PRODUCT_ID 0x0219 | ||
56 | |||
57 | /* | ||
58 | * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext | ||
59 | * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables | ||
60 | */ | ||
61 | #define GEYSER4_ANSI_PRODUCT_ID 0x021A | ||
62 | #define GEYSER4_ISO_PRODUCT_ID 0x021B | ||
63 | #define GEYSER4_JIS_PRODUCT_ID 0x021C | ||
64 | |||
65 | #define ATP_DEVICE(prod) \ | ||
66 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ | ||
67 | USB_DEVICE_ID_MATCH_INT_CLASS | \ | ||
68 | USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ | ||
69 | .idVendor = APPLE_VENDOR_ID, \ | ||
70 | .idProduct = (prod), \ | ||
71 | .bInterfaceClass = 0x03, \ | ||
72 | .bInterfaceProtocol = 0x02 | ||
73 | |||
74 | /* table of devices that work with this driver */ | ||
75 | static struct usb_device_id atp_table [] = { | ||
76 | { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) }, | ||
77 | { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) }, | ||
78 | { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) }, | ||
79 | { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) }, | ||
80 | |||
81 | /* PowerBooks Oct 2005 */ | ||
82 | { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) }, | ||
83 | { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, | ||
84 | { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, | ||
85 | |||
86 | /* Core Duo MacBook & MacBook Pro */ | ||
87 | { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) }, | ||
88 | { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) }, | ||
89 | { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) }, | ||
90 | |||
91 | /* Core2 Duo MacBook & MacBook Pro */ | ||
92 | { ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) }, | ||
93 | { ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) }, | ||
94 | { ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) }, | ||
95 | |||
96 | /* Terminating entry */ | ||
97 | { } | ||
98 | }; | ||
99 | MODULE_DEVICE_TABLE (usb, atp_table); | ||
100 | |||
101 | /* | ||
102 | * number of sensors. Note that only 16 instead of 26 X (horizontal) | ||
103 | * sensors exist on 12" and 15" PowerBooks. All models have 16 Y | ||
104 | * (vertical) sensors. | ||
105 | */ | ||
106 | #define ATP_XSENSORS 26 | ||
107 | #define ATP_YSENSORS 16 | ||
108 | |||
109 | /* amount of fuzz this touchpad generates */ | ||
110 | #define ATP_FUZZ 16 | ||
111 | |||
112 | /* maximum pressure this driver will report */ | ||
113 | #define ATP_PRESSURE 300 | ||
114 | /* | ||
115 | * multiplication factor for the X and Y coordinates. | ||
116 | * We try to keep the touchpad aspect ratio while still doing only simple | ||
117 | * arithmetics. | ||
118 | * The factors below give coordinates like: | ||
119 | * 0 <= x < 960 on 12" and 15" Powerbooks | ||
120 | * 0 <= x < 1600 on 17" Powerbooks | ||
121 | * 0 <= y < 646 | ||
122 | */ | ||
123 | #define ATP_XFACT 64 | ||
124 | #define ATP_YFACT 43 | ||
125 | |||
126 | /* | ||
127 | * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is | ||
128 | * ignored. | ||
129 | */ | ||
130 | #define ATP_THRESHOLD 5 | ||
131 | |||
132 | /* MacBook Pro (Geyser 3 & 4) initialization constants */ | ||
133 | #define ATP_GEYSER3_MODE_READ_REQUEST_ID 1 | ||
134 | #define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9 | ||
135 | #define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300 | ||
136 | #define ATP_GEYSER3_MODE_REQUEST_INDEX 0 | ||
137 | #define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04 | ||
138 | |||
139 | /* Structure to hold all of our device specific stuff */ | ||
140 | struct atp { | ||
141 | char phys[64]; | ||
142 | struct usb_device * udev; /* usb device */ | ||
143 | struct urb * urb; /* usb request block */ | ||
144 | signed char * data; /* transferred data */ | ||
145 | int open; /* non-zero if opened */ | ||
146 | struct input_dev *input; /* input dev */ | ||
147 | int valid; /* are the sensors valid ? */ | ||
148 | int x_old; /* last reported x/y, */ | ||
149 | int y_old; /* used for smoothing */ | ||
150 | /* current value of the sensors */ | ||
151 | signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; | ||
152 | /* last value of the sensors */ | ||
153 | signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; | ||
154 | /* accumulated sensors */ | ||
155 | int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; | ||
156 | int overflowwarn; /* overflow warning printed? */ | ||
157 | int datalen; /* size of an USB urb transfer */ | ||
158 | }; | ||
159 | |||
160 | #define dbg_dump(msg, tab) \ | ||
161 | if (debug > 1) { \ | ||
162 | int i; \ | ||
163 | printk("appletouch: %s %lld", msg, (long long)jiffies); \ | ||
164 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \ | ||
165 | printk(" %02x", tab[i]); \ | ||
166 | printk("\n"); \ | ||
167 | } | ||
168 | |||
169 | #define dprintk(format, a...) \ | ||
170 | do { \ | ||
171 | if (debug) printk(format, ##a); \ | ||
172 | } while (0) | ||
173 | |||
174 | MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann"); | ||
175 | MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver"); | ||
176 | MODULE_LICENSE("GPL"); | ||
177 | |||
178 | /* | ||
179 | * Make the threshold a module parameter | ||
180 | */ | ||
181 | static int threshold = ATP_THRESHOLD; | ||
182 | module_param(threshold, int, 0644); | ||
183 | MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value"); | ||
184 | |||
185 | static int debug = 1; | ||
186 | module_param(debug, int, 0644); | ||
187 | MODULE_PARM_DESC(debug, "Activate debugging output"); | ||
188 | |||
189 | /* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ | ||
190 | static inline int atp_is_geyser_2(struct atp *dev) | ||
191 | { | ||
192 | u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); | ||
193 | |||
194 | return (productId == GEYSER_ANSI_PRODUCT_ID) || | ||
195 | (productId == GEYSER_ISO_PRODUCT_ID) || | ||
196 | (productId == GEYSER_JIS_PRODUCT_ID); | ||
197 | } | ||
198 | |||
199 | static inline int atp_is_geyser_3(struct atp *dev) | ||
200 | { | ||
201 | u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); | ||
202 | |||
203 | return (productId == GEYSER3_ANSI_PRODUCT_ID) || | ||
204 | (productId == GEYSER3_ISO_PRODUCT_ID) || | ||
205 | (productId == GEYSER3_JIS_PRODUCT_ID) || | ||
206 | (productId == GEYSER4_ANSI_PRODUCT_ID) || | ||
207 | (productId == GEYSER4_ISO_PRODUCT_ID) || | ||
208 | (productId == GEYSER4_JIS_PRODUCT_ID); | ||
209 | } | ||
210 | |||
211 | static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, | ||
212 | int *z, int *fingers) | ||
213 | { | ||
214 | int i; | ||
215 | /* values to calculate mean */ | ||
216 | int pcum = 0, psum = 0; | ||
217 | int is_increasing = 0; | ||
218 | |||
219 | *fingers = 0; | ||
220 | |||
221 | for (i = 0; i < nb_sensors; i++) { | ||
222 | if (xy_sensors[i] < threshold) { | ||
223 | if (is_increasing) | ||
224 | is_increasing = 0; | ||
225 | |||
226 | continue; | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * Makes the finger detection more versatile. For example, | ||
231 | * two fingers with no gap will be detected. Also, my | ||
232 | * tests show it less likely to have intermittent loss | ||
233 | * of multiple finger readings while moving around (scrolling). | ||
234 | * | ||
235 | * Changes the multiple finger detection to counting humps on | ||
236 | * sensors (transitions from nonincreasing to increasing) | ||
237 | * instead of counting transitions from low sensors (no | ||
238 | * finger reading) to high sensors (finger above | ||
239 | * sensor) | ||
240 | * | ||
241 | * - Jason Parekh <jasonparekh@gmail.com> | ||
242 | */ | ||
243 | if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { | ||
244 | (*fingers)++; | ||
245 | is_increasing = 1; | ||
246 | } else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) { | ||
247 | is_increasing = 0; | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * Subtracts threshold so a high sensor that just passes the threshold | ||
252 | * won't skew the calculated absolute coordinate. Fixes an issue | ||
253 | * where slowly moving the mouse would occassionaly jump a number of | ||
254 | * pixels (let me restate--slowly moving the mouse makes this issue | ||
255 | * most apparent). | ||
256 | */ | ||
257 | pcum += (xy_sensors[i] - threshold) * i; | ||
258 | psum += (xy_sensors[i] - threshold); | ||
259 | } | ||
260 | |||
261 | if (psum > 0) { | ||
262 | *z = psum; | ||
263 | return pcum * fact / psum; | ||
264 | } | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static inline void atp_report_fingers(struct input_dev *input, int fingers) | ||
270 | { | ||
271 | input_report_key(input, BTN_TOOL_FINGER, fingers == 1); | ||
272 | input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2); | ||
273 | input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); | ||
274 | } | ||
275 | |||
276 | static void atp_complete(struct urb* urb) | ||
277 | { | ||
278 | int x, y, x_z, y_z, x_f, y_f; | ||
279 | int retval, i, j; | ||
280 | struct atp *dev = urb->context; | ||
281 | |||
282 | switch (urb->status) { | ||
283 | case 0: | ||
284 | /* success */ | ||
285 | break; | ||
286 | case -EOVERFLOW: | ||
287 | if(!dev->overflowwarn) { | ||
288 | printk("appletouch: OVERFLOW with data " | ||
289 | "length %d, actual length is %d\n", | ||
290 | dev->datalen, dev->urb->actual_length); | ||
291 | dev->overflowwarn = 1; | ||
292 | } | ||
293 | case -ECONNRESET: | ||
294 | case -ENOENT: | ||
295 | case -ESHUTDOWN: | ||
296 | /* This urb is terminated, clean up */ | ||
297 | dbg("%s - urb shutting down with status: %d", | ||
298 | __FUNCTION__, urb->status); | ||
299 | return; | ||
300 | default: | ||
301 | dbg("%s - nonzero urb status received: %d", | ||
302 | __FUNCTION__, urb->status); | ||
303 | goto exit; | ||
304 | } | ||
305 | |||
306 | /* drop incomplete datasets */ | ||
307 | if (dev->urb->actual_length != dev->datalen) { | ||
308 | dprintk("appletouch: incomplete data package" | ||
309 | " (first byte: %d, length: %d).\n", | ||
310 | dev->data[0], dev->urb->actual_length); | ||
311 | goto exit; | ||
312 | } | ||
313 | |||
314 | /* reorder the sensors values */ | ||
315 | if (atp_is_geyser_3(dev)) { | ||
316 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | ||
317 | |||
318 | /* | ||
319 | * The values are laid out like this: | ||
320 | * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... | ||
321 | * '-' is an unused value. | ||
322 | */ | ||
323 | |||
324 | /* read X values */ | ||
325 | for (i = 0, j = 19; i < 20; i += 2, j += 3) { | ||
326 | dev->xy_cur[i] = dev->data[j + 1]; | ||
327 | dev->xy_cur[i + 1] = dev->data[j + 2]; | ||
328 | } | ||
329 | /* read Y values */ | ||
330 | for (i = 0, j = 1; i < 9; i += 2, j += 3) { | ||
331 | dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; | ||
332 | dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; | ||
333 | } | ||
334 | } else if (atp_is_geyser_2(dev)) { | ||
335 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | ||
336 | |||
337 | /* | ||
338 | * The values are laid out like this: | ||
339 | * Y1, Y2, -, Y3, Y4, -, ..., X1, X2, -, X3, X4, -, ... | ||
340 | * '-' is an unused value. | ||
341 | */ | ||
342 | |||
343 | /* read X values */ | ||
344 | for (i = 0, j = 19; i < 20; i += 2, j += 3) { | ||
345 | dev->xy_cur[i] = dev->data[j]; | ||
346 | dev->xy_cur[i + 1] = dev->data[j + 1]; | ||
347 | } | ||
348 | |||
349 | /* read Y values */ | ||
350 | for (i = 0, j = 1; i < 9; i += 2, j += 3) { | ||
351 | dev->xy_cur[ATP_XSENSORS + i] = dev->data[j]; | ||
352 | dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 1]; | ||
353 | } | ||
354 | } else { | ||
355 | for (i = 0; i < 8; i++) { | ||
356 | /* X values */ | ||
357 | dev->xy_cur[i ] = dev->data[5 * i + 2]; | ||
358 | dev->xy_cur[i + 8] = dev->data[5 * i + 4]; | ||
359 | dev->xy_cur[i + 16] = dev->data[5 * i + 42]; | ||
360 | if (i < 2) | ||
361 | dev->xy_cur[i + 24] = dev->data[5 * i + 44]; | ||
362 | |||
363 | /* Y values */ | ||
364 | dev->xy_cur[i + 26] = dev->data[5 * i + 1]; | ||
365 | dev->xy_cur[i + 34] = dev->data[5 * i + 3]; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | dbg_dump("sample", dev->xy_cur); | ||
370 | |||
371 | if (!dev->valid) { | ||
372 | /* first sample */ | ||
373 | dev->valid = 1; | ||
374 | dev->x_old = dev->y_old = -1; | ||
375 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | ||
376 | |||
377 | if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */ | ||
378 | goto exit; | ||
379 | |||
380 | /* 17" Powerbooks have extra X sensors */ | ||
381 | for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { | ||
382 | if (!dev->xy_cur[i]) continue; | ||
383 | |||
384 | printk("appletouch: 17\" model detected.\n"); | ||
385 | if(atp_is_geyser_2(dev)) | ||
386 | input_set_abs_params(dev->input, ABS_X, 0, | ||
387 | (20 - 1) * | ||
388 | ATP_XFACT - 1, | ||
389 | ATP_FUZZ, 0); | ||
390 | else | ||
391 | input_set_abs_params(dev->input, ABS_X, 0, | ||
392 | (ATP_XSENSORS - 1) * | ||
393 | ATP_XFACT - 1, | ||
394 | ATP_FUZZ, 0); | ||
395 | |||
396 | break; | ||
397 | } | ||
398 | |||
399 | goto exit; | ||
400 | } | ||
401 | |||
402 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { | ||
403 | /* accumulate the change */ | ||
404 | signed char change = dev->xy_old[i] - dev->xy_cur[i]; | ||
405 | dev->xy_acc[i] -= change; | ||
406 | |||
407 | /* prevent down drifting */ | ||
408 | if (dev->xy_acc[i] < 0) | ||
409 | dev->xy_acc[i] = 0; | ||
410 | } | ||
411 | |||
412 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | ||
413 | |||
414 | dbg_dump("accumulator", dev->xy_acc); | ||
415 | |||
416 | x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, | ||
417 | ATP_XFACT, &x_z, &x_f); | ||
418 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, | ||
419 | ATP_YFACT, &y_z, &y_f); | ||
420 | |||
421 | if (x && y) { | ||
422 | if (dev->x_old != -1) { | ||
423 | x = (dev->x_old * 3 + x) >> 2; | ||
424 | y = (dev->y_old * 3 + y) >> 2; | ||
425 | dev->x_old = x; | ||
426 | dev->y_old = y; | ||
427 | |||
428 | if (debug > 1) | ||
429 | printk("appletouch: X: %3d Y: %3d " | ||
430 | "Xz: %3d Yz: %3d\n", | ||
431 | x, y, x_z, y_z); | ||
432 | |||
433 | input_report_key(dev->input, BTN_TOUCH, 1); | ||
434 | input_report_abs(dev->input, ABS_X, x); | ||
435 | input_report_abs(dev->input, ABS_Y, y); | ||
436 | input_report_abs(dev->input, ABS_PRESSURE, | ||
437 | min(ATP_PRESSURE, x_z + y_z)); | ||
438 | atp_report_fingers(dev->input, max(x_f, y_f)); | ||
439 | } | ||
440 | dev->x_old = x; | ||
441 | dev->y_old = y; | ||
442 | } | ||
443 | else if (!x && !y) { | ||
444 | |||
445 | dev->x_old = dev->y_old = -1; | ||
446 | input_report_key(dev->input, BTN_TOUCH, 0); | ||
447 | input_report_abs(dev->input, ABS_PRESSURE, 0); | ||
448 | atp_report_fingers(dev->input, 0); | ||
449 | |||
450 | /* reset the accumulator on release */ | ||
451 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); | ||
452 | } | ||
453 | |||
454 | input_report_key(dev->input, BTN_LEFT, | ||
455 | !!dev->data[dev->datalen - 1]); | ||
456 | |||
457 | input_sync(dev->input); | ||
458 | |||
459 | exit: | ||
460 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); | ||
461 | if (retval) { | ||
462 | err("%s - usb_submit_urb failed with result %d", | ||
463 | __FUNCTION__, retval); | ||
464 | } | ||
465 | } | ||
466 | |||
467 | static int atp_open(struct input_dev *input) | ||
468 | { | ||
469 | struct atp *dev = input_get_drvdata(input); | ||
470 | |||
471 | if (usb_submit_urb(dev->urb, GFP_ATOMIC)) | ||
472 | return -EIO; | ||
473 | |||
474 | dev->open = 1; | ||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static void atp_close(struct input_dev *input) | ||
479 | { | ||
480 | struct atp *dev = input_get_drvdata(input); | ||
481 | |||
482 | usb_kill_urb(dev->urb); | ||
483 | dev->open = 0; | ||
484 | } | ||
485 | |||
486 | static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id) | ||
487 | { | ||
488 | struct atp *dev; | ||
489 | struct input_dev *input_dev; | ||
490 | struct usb_device *udev = interface_to_usbdev(iface); | ||
491 | struct usb_host_interface *iface_desc; | ||
492 | struct usb_endpoint_descriptor *endpoint; | ||
493 | int int_in_endpointAddr = 0; | ||
494 | int i, error = -ENOMEM; | ||
495 | |||
496 | /* set up the endpoint information */ | ||
497 | /* use only the first interrupt-in endpoint */ | ||
498 | iface_desc = iface->cur_altsetting; | ||
499 | for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { | ||
500 | endpoint = &iface_desc->endpoint[i].desc; | ||
501 | if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) { | ||
502 | /* we found an interrupt in endpoint */ | ||
503 | int_in_endpointAddr = endpoint->bEndpointAddress; | ||
504 | break; | ||
505 | } | ||
506 | } | ||
507 | if (!int_in_endpointAddr) { | ||
508 | err("Could not find int-in endpoint"); | ||
509 | return -EIO; | ||
510 | } | ||
511 | |||
512 | /* allocate memory for our device state and initialize it */ | ||
513 | dev = kzalloc(sizeof(struct atp), GFP_KERNEL); | ||
514 | input_dev = input_allocate_device(); | ||
515 | if (!dev || !input_dev) { | ||
516 | err("Out of memory"); | ||
517 | goto err_free_devs; | ||
518 | } | ||
519 | |||
520 | dev->udev = udev; | ||
521 | dev->input = input_dev; | ||
522 | dev->overflowwarn = 0; | ||
523 | if (atp_is_geyser_3(dev)) | ||
524 | dev->datalen = 64; | ||
525 | else if (atp_is_geyser_2(dev)) | ||
526 | dev->datalen = 64; | ||
527 | else | ||
528 | dev->datalen = 81; | ||
529 | |||
530 | if (atp_is_geyser_3(dev)) { | ||
531 | /* | ||
532 | * By default Geyser 3 device sends standard USB HID mouse | ||
533 | * packets (Report ID 2). This code changes device mode, so it | ||
534 | * sends raw sensor reports (Report ID 5). | ||
535 | */ | ||
536 | char data[8]; | ||
537 | int size; | ||
538 | |||
539 | size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
540 | ATP_GEYSER3_MODE_READ_REQUEST_ID, | ||
541 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
542 | ATP_GEYSER3_MODE_REQUEST_VALUE, | ||
543 | ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); | ||
544 | |||
545 | if (size != 8) { | ||
546 | err("Could not do mode read request from device" | ||
547 | " (Geyser 3 mode)"); | ||
548 | goto err_free_devs; | ||
549 | } | ||
550 | |||
551 | /* Apply the mode switch */ | ||
552 | data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE; | ||
553 | |||
554 | size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
555 | ATP_GEYSER3_MODE_WRITE_REQUEST_ID, | ||
556 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
557 | ATP_GEYSER3_MODE_REQUEST_VALUE, | ||
558 | ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); | ||
559 | |||
560 | if (size != 8) { | ||
561 | err("Could not do mode write request to device" | ||
562 | " (Geyser 3 mode)"); | ||
563 | goto err_free_devs; | ||
564 | } | ||
565 | printk("appletouch Geyser 3 inited.\n"); | ||
566 | } | ||
567 | |||
568 | dev->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
569 | if (!dev->urb) | ||
570 | goto err_free_devs; | ||
571 | |||
572 | dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL, | ||
573 | &dev->urb->transfer_dma); | ||
574 | if (!dev->data) | ||
575 | goto err_free_urb; | ||
576 | |||
577 | usb_fill_int_urb(dev->urb, udev, | ||
578 | usb_rcvintpipe(udev, int_in_endpointAddr), | ||
579 | dev->data, dev->datalen, atp_complete, dev, 1); | ||
580 | |||
581 | usb_make_path(udev, dev->phys, sizeof(dev->phys)); | ||
582 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); | ||
583 | |||
584 | input_dev->name = "appletouch"; | ||
585 | input_dev->phys = dev->phys; | ||
586 | usb_to_input_id(dev->udev, &input_dev->id); | ||
587 | input_dev->dev.parent = &iface->dev; | ||
588 | |||
589 | input_set_drvdata(input_dev, dev); | ||
590 | |||
591 | input_dev->open = atp_open; | ||
592 | input_dev->close = atp_close; | ||
593 | |||
594 | set_bit(EV_ABS, input_dev->evbit); | ||
595 | |||
596 | if (atp_is_geyser_3(dev)) { | ||
597 | /* | ||
598 | * MacBook have 20 X sensors, 10 Y sensors | ||
599 | */ | ||
600 | input_set_abs_params(input_dev, ABS_X, 0, | ||
601 | ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0); | ||
602 | input_set_abs_params(input_dev, ABS_Y, 0, | ||
603 | ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0); | ||
604 | } else if (atp_is_geyser_2(dev)) { | ||
605 | /* | ||
606 | * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected | ||
607 | * later. | ||
608 | */ | ||
609 | input_set_abs_params(input_dev, ABS_X, 0, | ||
610 | ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0); | ||
611 | input_set_abs_params(input_dev, ABS_Y, 0, | ||
612 | ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0); | ||
613 | } else { | ||
614 | /* | ||
615 | * 12" and 15" Powerbooks only have 16 x sensors, | ||
616 | * 17" models are detected later. | ||
617 | */ | ||
618 | input_set_abs_params(input_dev, ABS_X, 0, | ||
619 | (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); | ||
620 | input_set_abs_params(input_dev, ABS_Y, 0, | ||
621 | (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0); | ||
622 | } | ||
623 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); | ||
624 | |||
625 | set_bit(EV_KEY, input_dev->evbit); | ||
626 | set_bit(BTN_TOUCH, input_dev->keybit); | ||
627 | set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
628 | set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
629 | set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | ||
630 | set_bit(BTN_LEFT, input_dev->keybit); | ||
631 | |||
632 | error = input_register_device(dev->input); | ||
633 | if (error) | ||
634 | goto err_free_buffer; | ||
635 | |||
636 | /* save our data pointer in this interface device */ | ||
637 | usb_set_intfdata(iface, dev); | ||
638 | |||
639 | return 0; | ||
640 | |||
641 | err_free_buffer: | ||
642 | usb_buffer_free(dev->udev, dev->datalen, | ||
643 | dev->data, dev->urb->transfer_dma); | ||
644 | err_free_urb: | ||
645 | usb_free_urb(dev->urb); | ||
646 | err_free_devs: | ||
647 | usb_set_intfdata(iface, NULL); | ||
648 | kfree(dev); | ||
649 | input_free_device(input_dev); | ||
650 | return error; | ||
651 | } | ||
652 | |||
653 | static void atp_disconnect(struct usb_interface *iface) | ||
654 | { | ||
655 | struct atp *dev = usb_get_intfdata(iface); | ||
656 | |||
657 | usb_set_intfdata(iface, NULL); | ||
658 | if (dev) { | ||
659 | usb_kill_urb(dev->urb); | ||
660 | input_unregister_device(dev->input); | ||
661 | usb_buffer_free(dev->udev, dev->datalen, | ||
662 | dev->data, dev->urb->transfer_dma); | ||
663 | usb_free_urb(dev->urb); | ||
664 | kfree(dev); | ||
665 | } | ||
666 | printk(KERN_INFO "input: appletouch disconnected\n"); | ||
667 | } | ||
668 | |||
669 | static int atp_suspend(struct usb_interface *iface, pm_message_t message) | ||
670 | { | ||
671 | struct atp *dev = usb_get_intfdata(iface); | ||
672 | usb_kill_urb(dev->urb); | ||
673 | dev->valid = 0; | ||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | static int atp_resume(struct usb_interface *iface) | ||
678 | { | ||
679 | struct atp *dev = usb_get_intfdata(iface); | ||
680 | if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC)) | ||
681 | return -EIO; | ||
682 | |||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | static struct usb_driver atp_driver = { | ||
687 | .name = "appletouch", | ||
688 | .probe = atp_probe, | ||
689 | .disconnect = atp_disconnect, | ||
690 | .suspend = atp_suspend, | ||
691 | .resume = atp_resume, | ||
692 | .id_table = atp_table, | ||
693 | }; | ||
694 | |||
695 | static int __init atp_init(void) | ||
696 | { | ||
697 | return usb_register(&atp_driver); | ||
698 | } | ||
699 | |||
700 | static void __exit atp_exit(void) | ||
701 | { | ||
702 | usb_deregister(&atp_driver); | ||
703 | } | ||
704 | |||
705 | module_init(atp_init); | ||
706 | module_exit(atp_exit); | ||
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index c77788bf932d..666ad3a53fdb 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -185,7 +185,7 @@ static int synaptics_query_hardware(struct psmouse *psmouse) | |||
185 | int retries = 0; | 185 | int retries = 0; |
186 | 186 | ||
187 | while ((retries++ < 3) && psmouse_reset(psmouse)) | 187 | while ((retries++ < 3) && psmouse_reset(psmouse)) |
188 | printk(KERN_ERR "synaptics reset failed\n"); | 188 | /* empty */; |
189 | 189 | ||
190 | if (synaptics_identify(psmouse)) | 190 | if (synaptics_identify(psmouse)) |
191 | return -1; | 191 | return -1; |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 7c17377a65b9..3888dc307e0c 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -526,6 +526,33 @@ static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) | |||
526 | return IRQ_HANDLED; | 526 | return IRQ_HANDLED; |
527 | } | 527 | } |
528 | 528 | ||
529 | /* | ||
530 | * i8042_toggle_aux - enables or disables AUX port on i8042 via command and | ||
531 | * verifies success by readinng CTR. Used when testing for presence of AUX | ||
532 | * port. | ||
533 | */ | ||
534 | static int __devinit i8042_toggle_aux(int on) | ||
535 | { | ||
536 | unsigned char param; | ||
537 | int i; | ||
538 | |||
539 | if (i8042_command(¶m, | ||
540 | on ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE)) | ||
541 | return -1; | ||
542 | |||
543 | /* some chips need some time to set the I8042_CTR_AUXDIS bit */ | ||
544 | for (i = 0; i < 100; i++) { | ||
545 | udelay(50); | ||
546 | |||
547 | if (i8042_command(¶m, I8042_CMD_CTL_RCTR)) | ||
548 | return -1; | ||
549 | |||
550 | if (!(param & I8042_CTR_AUXDIS) == on) | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | return -1; | ||
555 | } | ||
529 | 556 | ||
530 | /* | 557 | /* |
531 | * i8042_check_aux() applies as much paranoia as it can at detecting | 558 | * i8042_check_aux() applies as much paranoia as it can at detecting |
@@ -580,16 +607,12 @@ static int __devinit i8042_check_aux(void) | |||
580 | * Bit assignment test - filters out PS/2 i8042's in AT mode | 607 | * Bit assignment test - filters out PS/2 i8042's in AT mode |
581 | */ | 608 | */ |
582 | 609 | ||
583 | if (i8042_command(¶m, I8042_CMD_AUX_DISABLE)) | 610 | if (i8042_toggle_aux(0)) { |
584 | return -1; | ||
585 | if (i8042_command(¶m, I8042_CMD_CTL_RCTR) || (~param & I8042_CTR_AUXDIS)) { | ||
586 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); | 611 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); |
587 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); | 612 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); |
588 | } | 613 | } |
589 | 614 | ||
590 | if (i8042_command(¶m, I8042_CMD_AUX_ENABLE)) | 615 | if (i8042_toggle_aux(1)) |
591 | return -1; | ||
592 | if (i8042_command(¶m, I8042_CMD_CTL_RCTR) || (param & I8042_CTR_AUXDIS)) | ||
593 | return -1; | 616 | return -1; |
594 | 617 | ||
595 | /* | 618 | /* |
diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig new file mode 100644 index 000000000000..12dfb0eb3262 --- /dev/null +++ b/drivers/input/tablet/Kconfig | |||
@@ -0,0 +1,74 @@ | |||
1 | # | ||
2 | # Tablet driver configuration | ||
3 | # | ||
4 | menuconfig INPUT_TABLET | ||
5 | bool "Tablets" | ||
6 | help | ||
7 | Say Y here, and a list of supported tablets will be displayed. | ||
8 | This option doesn't affect the kernel. | ||
9 | |||
10 | If unsure, say Y. | ||
11 | |||
12 | if INPUT_TABLET | ||
13 | |||
14 | config TABLET_USB_ACECAD | ||
15 | tristate "Acecad Flair tablet support (USB)" | ||
16 | select USB | ||
17 | help | ||
18 | Say Y here if you want to use the USB version of the Acecad Flair | ||
19 | tablet. Make sure to say Y to "Mouse support" | ||
20 | (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" | ||
21 | (CONFIG_INPUT_EVDEV) as well. | ||
22 | |||
23 | To compile this driver as a module, choose M here: the | ||
24 | module will be called acecad. | ||
25 | |||
26 | config TABLET_USB_AIPTEK | ||
27 | tristate "Aiptek 6000U/8000U tablet support (USB)" | ||
28 | select USB | ||
29 | help | ||
30 | Say Y here if you want to use the USB version of the Aiptek 6000U | ||
31 | or Aiptek 8000U tablet. Make sure to say Y to "Mouse support" | ||
32 | (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" | ||
33 | (CONFIG_INPUT_EVDEV) as well. | ||
34 | |||
35 | To compile this driver as a module, choose M here: the | ||
36 | module will be called aiptek. | ||
37 | |||
38 | config TABLET_USB_GTCO | ||
39 | tristate "GTCO CalComp/InterWrite USB Support" | ||
40 | depends on USB && INPUT | ||
41 | help | ||
42 | Say Y here if you want to use the USB version of the GTCO | ||
43 | CalComp/InterWrite Tablet. Make sure to say Y to "Mouse support" | ||
44 | (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" | ||
45 | (CONFIG_INPUT_EVDEV) as well. | ||
46 | |||
47 | To compile this driver as a module, choose M here: the | ||
48 | module will be called gtco. | ||
49 | |||
50 | config TABLET_USB_KBTAB | ||
51 | tristate "KB Gear JamStudio tablet support (USB)" | ||
52 | select USB | ||
53 | help | ||
54 | Say Y here if you want to use the USB version of the KB Gear | ||
55 | JamStudio tablet. Make sure to say Y to "Mouse support" | ||
56 | (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" | ||
57 | (CONFIG_INPUT_EVDEV) as well. | ||
58 | |||
59 | To compile this driver as a module, choose M here: the | ||
60 | module will be called kbtab. | ||
61 | |||
62 | config TABLET_USB_WACOM | ||
63 | tristate "Wacom Intuos/Graphire tablet support (USB)" | ||
64 | select USB | ||
65 | help | ||
66 | Say Y here if you want to use the USB version of the Wacom Intuos | ||
67 | or Graphire tablet. Make sure to say Y to "Mouse support" | ||
68 | (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" | ||
69 | (CONFIG_INPUT_EVDEV) as well. | ||
70 | |||
71 | To compile this driver as a module, choose M here: the | ||
72 | module will be called wacom. | ||
73 | |||
74 | endif | ||
diff --git a/drivers/input/tablet/Makefile b/drivers/input/tablet/Makefile new file mode 100644 index 000000000000..ce8b9a9cfa40 --- /dev/null +++ b/drivers/input/tablet/Makefile | |||
@@ -0,0 +1,12 @@ | |||
1 | # | ||
2 | # Makefile for the tablet drivers | ||
3 | # | ||
4 | |||
5 | # Multipart objects. | ||
6 | wacom-objs := wacom_wac.o wacom_sys.o | ||
7 | |||
8 | obj-$(CONFIG_TABLET_USB_ACECAD) += acecad.o | ||
9 | obj-$(CONFIG_TABLET_USB_AIPTEK) += aiptek.o | ||
10 | obj-$(CONFIG_TABLET_USB_GTCO) += gtco.o | ||
11 | obj-$(CONFIG_TABLET_USB_KBTAB) += kbtab.o | ||
12 | obj-$(CONFIG_TABLET_USB_WACOM) += wacom.o | ||
diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c new file mode 100644 index 000000000000..dd2310458c46 --- /dev/null +++ b/drivers/input/tablet/acecad.c | |||
@@ -0,0 +1,289 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2001-2005 Edouard TISSERANT <edouard.tisserant@wanadoo.fr> | ||
3 | * Copyright (c) 2004-2005 Stephane VOLTZ <svoltz@numericable.fr> | ||
4 | * | ||
5 | * USB Acecad "Acecad Flair" tablet support | ||
6 | * | ||
7 | * Changelog: | ||
8 | * v3.2 - Added sysfs support | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/usb/input.h> | ||
33 | |||
34 | /* | ||
35 | * Version Information | ||
36 | */ | ||
37 | #define DRIVER_VERSION "v3.2" | ||
38 | #define DRIVER_DESC "USB Acecad Flair tablet driver" | ||
39 | #define DRIVER_LICENSE "GPL" | ||
40 | #define DRIVER_AUTHOR "Edouard TISSERANT <edouard.tisserant@wanadoo.fr>" | ||
41 | |||
42 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
43 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
44 | MODULE_LICENSE(DRIVER_LICENSE); | ||
45 | |||
46 | #define USB_VENDOR_ID_ACECAD 0x0460 | ||
47 | #define USB_DEVICE_ID_FLAIR 0x0004 | ||
48 | #define USB_DEVICE_ID_302 0x0008 | ||
49 | |||
50 | struct usb_acecad { | ||
51 | char name[128]; | ||
52 | char phys[64]; | ||
53 | struct usb_device *usbdev; | ||
54 | struct input_dev *input; | ||
55 | struct urb *irq; | ||
56 | |||
57 | unsigned char *data; | ||
58 | dma_addr_t data_dma; | ||
59 | }; | ||
60 | |||
61 | static void usb_acecad_irq(struct urb *urb) | ||
62 | { | ||
63 | struct usb_acecad *acecad = urb->context; | ||
64 | unsigned char *data = acecad->data; | ||
65 | struct input_dev *dev = acecad->input; | ||
66 | int prox, status; | ||
67 | |||
68 | switch (urb->status) { | ||
69 | case 0: | ||
70 | /* success */ | ||
71 | break; | ||
72 | case -ECONNRESET: | ||
73 | case -ENOENT: | ||
74 | case -ESHUTDOWN: | ||
75 | /* this urb is terminated, clean up */ | ||
76 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
77 | return; | ||
78 | default: | ||
79 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
80 | goto resubmit; | ||
81 | } | ||
82 | |||
83 | prox = (data[0] & 0x04) >> 2; | ||
84 | input_report_key(dev, BTN_TOOL_PEN, prox); | ||
85 | |||
86 | if (prox) { | ||
87 | int x = data[1] | (data[2] << 8); | ||
88 | int y = data[3] | (data[4] << 8); | ||
89 | /* Pressure should compute the same way for flair and 302 */ | ||
90 | int pressure = data[5] | (data[6] << 8); | ||
91 | int touch = data[0] & 0x01; | ||
92 | int stylus = (data[0] & 0x10) >> 4; | ||
93 | int stylus2 = (data[0] & 0x20) >> 5; | ||
94 | input_report_abs(dev, ABS_X, x); | ||
95 | input_report_abs(dev, ABS_Y, y); | ||
96 | input_report_abs(dev, ABS_PRESSURE, pressure); | ||
97 | input_report_key(dev, BTN_TOUCH, touch); | ||
98 | input_report_key(dev, BTN_STYLUS, stylus); | ||
99 | input_report_key(dev, BTN_STYLUS2, stylus2); | ||
100 | } | ||
101 | |||
102 | /* event termination */ | ||
103 | input_sync(dev); | ||
104 | |||
105 | resubmit: | ||
106 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
107 | if (status) | ||
108 | err("can't resubmit intr, %s-%s/input0, status %d", | ||
109 | acecad->usbdev->bus->bus_name, acecad->usbdev->devpath, status); | ||
110 | } | ||
111 | |||
112 | static int usb_acecad_open(struct input_dev *dev) | ||
113 | { | ||
114 | struct usb_acecad *acecad = input_get_drvdata(dev); | ||
115 | |||
116 | acecad->irq->dev = acecad->usbdev; | ||
117 | if (usb_submit_urb(acecad->irq, GFP_KERNEL)) | ||
118 | return -EIO; | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static void usb_acecad_close(struct input_dev *dev) | ||
124 | { | ||
125 | struct usb_acecad *acecad = input_get_drvdata(dev); | ||
126 | |||
127 | usb_kill_urb(acecad->irq); | ||
128 | } | ||
129 | |||
130 | static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
131 | { | ||
132 | struct usb_device *dev = interface_to_usbdev(intf); | ||
133 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
134 | struct usb_endpoint_descriptor *endpoint; | ||
135 | struct usb_acecad *acecad; | ||
136 | struct input_dev *input_dev; | ||
137 | int pipe, maxp; | ||
138 | int err = -ENOMEM; | ||
139 | |||
140 | if (interface->desc.bNumEndpoints != 1) | ||
141 | return -ENODEV; | ||
142 | |||
143 | endpoint = &interface->endpoint[0].desc; | ||
144 | |||
145 | if (!usb_endpoint_is_int_in(endpoint)) | ||
146 | return -ENODEV; | ||
147 | |||
148 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
149 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
150 | |||
151 | acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL); | ||
152 | input_dev = input_allocate_device(); | ||
153 | if (!acecad || !input_dev) { | ||
154 | err = -ENOMEM; | ||
155 | goto fail1; | ||
156 | } | ||
157 | |||
158 | acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma); | ||
159 | if (!acecad->data) { | ||
160 | err= -ENOMEM; | ||
161 | goto fail1; | ||
162 | } | ||
163 | |||
164 | acecad->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
165 | if (!acecad->irq) { | ||
166 | err = -ENOMEM; | ||
167 | goto fail2; | ||
168 | } | ||
169 | |||
170 | acecad->usbdev = dev; | ||
171 | acecad->input = input_dev; | ||
172 | |||
173 | if (dev->manufacturer) | ||
174 | strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name)); | ||
175 | |||
176 | if (dev->product) { | ||
177 | if (dev->manufacturer) | ||
178 | strlcat(acecad->name, " ", sizeof(acecad->name)); | ||
179 | strlcat(acecad->name, dev->product, sizeof(acecad->name)); | ||
180 | } | ||
181 | |||
182 | usb_make_path(dev, acecad->phys, sizeof(acecad->phys)); | ||
183 | strlcat(acecad->phys, "/input0", sizeof(acecad->phys)); | ||
184 | |||
185 | input_dev->name = acecad->name; | ||
186 | input_dev->phys = acecad->phys; | ||
187 | usb_to_input_id(dev, &input_dev->id); | ||
188 | input_dev->dev.parent = &intf->dev; | ||
189 | |||
190 | input_set_drvdata(input_dev, acecad); | ||
191 | |||
192 | input_dev->open = usb_acecad_open; | ||
193 | input_dev->close = usb_acecad_close; | ||
194 | |||
195 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
196 | input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); | ||
197 | input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
198 | input_dev->keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2); | ||
199 | |||
200 | switch (id->driver_info) { | ||
201 | case 0: | ||
202 | input_dev->absmax[ABS_X] = 5000; | ||
203 | input_dev->absmax[ABS_Y] = 3750; | ||
204 | input_dev->absmax[ABS_PRESSURE] = 512; | ||
205 | if (!strlen(acecad->name)) | ||
206 | snprintf(acecad->name, sizeof(acecad->name), | ||
207 | "USB Acecad Flair Tablet %04x:%04x", | ||
208 | le16_to_cpu(dev->descriptor.idVendor), | ||
209 | le16_to_cpu(dev->descriptor.idProduct)); | ||
210 | break; | ||
211 | case 1: | ||
212 | input_dev->absmax[ABS_X] = 3000; | ||
213 | input_dev->absmax[ABS_Y] = 2250; | ||
214 | input_dev->absmax[ABS_PRESSURE] = 1024; | ||
215 | if (!strlen(acecad->name)) | ||
216 | snprintf(acecad->name, sizeof(acecad->name), | ||
217 | "USB Acecad 302 Tablet %04x:%04x", | ||
218 | le16_to_cpu(dev->descriptor.idVendor), | ||
219 | le16_to_cpu(dev->descriptor.idProduct)); | ||
220 | break; | ||
221 | } | ||
222 | |||
223 | input_dev->absfuzz[ABS_X] = 4; | ||
224 | input_dev->absfuzz[ABS_Y] = 4; | ||
225 | |||
226 | usb_fill_int_urb(acecad->irq, dev, pipe, | ||
227 | acecad->data, maxp > 8 ? 8 : maxp, | ||
228 | usb_acecad_irq, acecad, endpoint->bInterval); | ||
229 | acecad->irq->transfer_dma = acecad->data_dma; | ||
230 | acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
231 | |||
232 | err = input_register_device(acecad->input); | ||
233 | if (err) | ||
234 | goto fail2; | ||
235 | |||
236 | usb_set_intfdata(intf, acecad); | ||
237 | |||
238 | return 0; | ||
239 | |||
240 | fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma); | ||
241 | fail1: input_free_device(input_dev); | ||
242 | kfree(acecad); | ||
243 | return err; | ||
244 | } | ||
245 | |||
246 | static void usb_acecad_disconnect(struct usb_interface *intf) | ||
247 | { | ||
248 | struct usb_acecad *acecad = usb_get_intfdata(intf); | ||
249 | |||
250 | usb_set_intfdata(intf, NULL); | ||
251 | if (acecad) { | ||
252 | usb_kill_urb(acecad->irq); | ||
253 | input_unregister_device(acecad->input); | ||
254 | usb_free_urb(acecad->irq); | ||
255 | usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); | ||
256 | kfree(acecad); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | static struct usb_device_id usb_acecad_id_table [] = { | ||
261 | { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 }, | ||
262 | { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302), .driver_info = 1 }, | ||
263 | { } | ||
264 | }; | ||
265 | |||
266 | MODULE_DEVICE_TABLE(usb, usb_acecad_id_table); | ||
267 | |||
268 | static struct usb_driver usb_acecad_driver = { | ||
269 | .name = "usb_acecad", | ||
270 | .probe = usb_acecad_probe, | ||
271 | .disconnect = usb_acecad_disconnect, | ||
272 | .id_table = usb_acecad_id_table, | ||
273 | }; | ||
274 | |||
275 | static int __init usb_acecad_init(void) | ||
276 | { | ||
277 | int result = usb_register(&usb_acecad_driver); | ||
278 | if (result == 0) | ||
279 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
280 | return result; | ||
281 | } | ||
282 | |||
283 | static void __exit usb_acecad_exit(void) | ||
284 | { | ||
285 | usb_deregister(&usb_acecad_driver); | ||
286 | } | ||
287 | |||
288 | module_init(usb_acecad_init); | ||
289 | module_exit(usb_acecad_exit); | ||
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c new file mode 100644 index 000000000000..cc0a498763d8 --- /dev/null +++ b/drivers/input/tablet/aiptek.c | |||
@@ -0,0 +1,2236 @@ | |||
1 | /* | ||
2 | * Native support for the Aiptek HyperPen USB Tablets | ||
3 | * (4000U/5000U/6000U/8000U/12000U) | ||
4 | * | ||
5 | * Copyright (c) 2001 Chris Atenasio <chris@crud.net> | ||
6 | * Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net> | ||
7 | * | ||
8 | * based on wacom.c by | ||
9 | * Vojtech Pavlik <vojtech@suse.cz> | ||
10 | * Andreas Bach Aaen <abach@stofanet.dk> | ||
11 | * Clifford Wolf <clifford@clifford.at> | ||
12 | * Sam Mosel <sam.mosel@computer.org> | ||
13 | * James E. Blair <corvus@gnu.org> | ||
14 | * Daniel Egger <egger@suse.de> | ||
15 | * | ||
16 | * Many thanks to Oliver Kuechemann for his support. | ||
17 | * | ||
18 | * ChangeLog: | ||
19 | * v0.1 - Initial release | ||
20 | * v0.2 - Hack to get around fake event 28's. (Bryan W. Headley) | ||
21 | * v0.3 - Make URB dynamic (Bryan W. Headley, Jun-8-2002) | ||
22 | * Released to Linux 2.4.19 and 2.5.x | ||
23 | * v0.4 - Rewrote substantial portions of the code to deal with | ||
24 | * corrected control sequences, timing, dynamic configuration, | ||
25 | * support of 6000U - 12000U, procfs, and macro key support | ||
26 | * (Jan-1-2003 - Feb-5-2003, Bryan W. Headley) | ||
27 | * v1.0 - Added support for diagnostic messages, count of messages | ||
28 | * received from URB - Mar-8-2003, Bryan W. Headley | ||
29 | * v1.1 - added support for tablet resolution, changed DV and proximity | ||
30 | * some corrections - Jun-22-2003, martin schneebacher | ||
31 | * - Added support for the sysfs interface, deprecating the | ||
32 | * procfs interface for 2.5.x kernel. Also added support for | ||
33 | * Wheel command. Bryan W. Headley July-15-2003. | ||
34 | * v1.2 - Reworked jitter timer as a kernel thread. | ||
35 | * Bryan W. Headley November-28-2003/Jan-10-2004. | ||
36 | * v1.3 - Repaired issue of kernel thread going nuts on single-processor | ||
37 | * machines, introduced programmableDelay as a command line | ||
38 | * parameter. Feb 7 2004, Bryan W. Headley. | ||
39 | * v1.4 - Re-wire jitter so it does not require a thread. Courtesy of | ||
40 | * Rene van Paassen. Added reporting of physical pointer device | ||
41 | * (e.g., stylus, mouse in reports 2, 3, 4, 5. We don't know | ||
42 | * for reports 1, 6.) | ||
43 | * what physical device reports for reports 1, 6.) Also enabled | ||
44 | * MOUSE and LENS tool button modes. Renamed "rubber" to "eraser". | ||
45 | * Feb 20, 2004, Bryan W. Headley. | ||
46 | * v1.5 - Added previousJitterable, so we don't do jitter delay when the | ||
47 | * user is holding a button down for periods of time. | ||
48 | * | ||
49 | * NOTE: | ||
50 | * This kernel driver is augmented by the "Aiptek" XFree86 input | ||
51 | * driver for your X server, as well as the Gaiptek GUI Front-end | ||
52 | * "Tablet Manager". | ||
53 | * These three products are highly interactive with one another, | ||
54 | * so therefore it's easier to document them all as one subsystem. | ||
55 | * Please visit the project's "home page", located at, | ||
56 | * http://aiptektablet.sourceforge.net. | ||
57 | * | ||
58 | * This program is free software; you can redistribute it and/or modify | ||
59 | * it under the terms of the GNU General Public License as published by | ||
60 | * the Free Software Foundation; either version 2 of the License, or | ||
61 | * (at your option) any later version. | ||
62 | * | ||
63 | * This program is distributed in the hope that it will be useful, | ||
64 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
65 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
66 | * GNU General Public License for more details. | ||
67 | * | ||
68 | * You should have received a copy of the GNU General Public License | ||
69 | * along with this program; if not, write to the Free Software | ||
70 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
71 | */ | ||
72 | |||
73 | #include <linux/jiffies.h> | ||
74 | #include <linux/kernel.h> | ||
75 | #include <linux/slab.h> | ||
76 | #include <linux/module.h> | ||
77 | #include <linux/init.h> | ||
78 | #include <linux/usb/input.h> | ||
79 | #include <asm/uaccess.h> | ||
80 | #include <asm/unaligned.h> | ||
81 | |||
82 | /* | ||
83 | * Version Information | ||
84 | */ | ||
85 | #define DRIVER_VERSION "v1.5 (May-15-2004)" | ||
86 | #define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio" | ||
87 | #define DRIVER_DESC "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)" | ||
88 | |||
89 | /* | ||
90 | * Aiptek status packet: | ||
91 | * | ||
92 | * (returned as Report 1 - relative coordinates from mouse and stylus) | ||
93 | * | ||
94 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | ||
95 | * byte0 0 0 0 0 0 0 0 1 | ||
96 | * byte1 0 0 0 0 0 BS2 BS Tip | ||
97 | * byte2 X7 X6 X5 X4 X3 X2 X1 X0 | ||
98 | * byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
99 | * | ||
100 | * (returned as Report 2 - absolute coordinates from the stylus) | ||
101 | * | ||
102 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | ||
103 | * byte0 0 0 0 0 0 0 1 0 | ||
104 | * byte1 X7 X6 X5 X4 X3 X2 X1 X0 | ||
105 | * byte2 X15 X14 X13 X12 X11 X10 X9 X8 | ||
106 | * byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
107 | * byte4 Y15 Y14 Y13 Y12 Y11 Y10 Y9 Y8 | ||
108 | * byte5 * * * BS2 BS1 Tip IR DV | ||
109 | * byte6 P7 P6 P5 P4 P3 P2 P1 P0 | ||
110 | * byte7 P15 P14 P13 P12 P11 P10 P9 P8 | ||
111 | * | ||
112 | * (returned as Report 3 - absolute coordinates from the mouse) | ||
113 | * | ||
114 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | ||
115 | * byte0 0 0 0 0 0 0 1 0 | ||
116 | * byte1 X7 X6 X5 X4 X3 X2 X1 X0 | ||
117 | * byte2 X15 X14 X13 X12 X11 X10 X9 X8 | ||
118 | * byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
119 | * byte4 Y15 Y14 Y13 Y12 Y11 Y10 Y9 Y8 | ||
120 | * byte5 * * * BS2 BS1 Tip IR DV | ||
121 | * byte6 P7 P6 P5 P4 P3 P2 P1 P0 | ||
122 | * byte7 P15 P14 P13 P12 P11 P10 P9 P8 | ||
123 | * | ||
124 | * (returned as Report 4 - macrokeys from the stylus) | ||
125 | * | ||
126 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | ||
127 | * byte0 0 0 0 0 0 1 0 0 | ||
128 | * byte1 0 0 0 BS2 BS Tip IR DV | ||
129 | * byte2 0 0 0 0 0 0 1 0 | ||
130 | * byte3 0 0 0 K4 K3 K2 K1 K0 | ||
131 | * byte4 P7 P6 P5 P4 P3 P2 P1 P0 | ||
132 | * byte5 P15 P14 P13 P12 P11 P10 P9 P8 | ||
133 | * | ||
134 | * (returned as Report 5 - macrokeys from the mouse) | ||
135 | * | ||
136 | * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 | ||
137 | * byte0 0 0 0 0 0 1 0 0 | ||
138 | * byte1 0 0 0 BS2 BS Tip IR DV | ||
139 | * byte2 0 0 0 0 0 0 1 0 | ||
140 | * byte3 0 0 0 K4 K3 K2 K1 K0 | ||
141 | * byte4 P7 P6 P5 P4 P3 P2 P1 P0 | ||
142 | * byte5 P15 P14 P13 P12 P11 P10 P9 P8 | ||
143 | * | ||
144 | * IR: In Range = Proximity on | ||
145 | * DV = Data Valid | ||
146 | * BS = Barrel Switch (as in, macro keys) | ||
147 | * BS2 also referred to as Tablet Pick | ||
148 | * | ||
149 | * Command Summary: | ||
150 | * | ||
151 | * Use report_type CONTROL (3) | ||
152 | * Use report_id 2 | ||
153 | * | ||
154 | * Command/Data Description Return Bytes Return Value | ||
155 | * 0x10/0x00 SwitchToMouse 0 | ||
156 | * 0x10/0x01 SwitchToTablet 0 | ||
157 | * 0x18/0x04 SetResolution 0 | ||
158 | * 0x12/0xFF AutoGainOn 0 | ||
159 | * 0x17/0x00 FilterOn 0 | ||
160 | * 0x01/0x00 GetXExtension 2 MaxX | ||
161 | * 0x01/0x01 GetYExtension 2 MaxY | ||
162 | * 0x02/0x00 GetModelCode 2 ModelCode = LOBYTE | ||
163 | * 0x03/0x00 GetODMCode 2 ODMCode | ||
164 | * 0x08/0x00 GetPressureLevels 2 =512 | ||
165 | * 0x04/0x00 GetFirmwareVersion 2 Firmware Version | ||
166 | * 0x11/0x02 EnableMacroKeys 0 | ||
167 | * | ||
168 | * To initialize the tablet: | ||
169 | * | ||
170 | * (1) Send Resolution500LPI (Command) | ||
171 | * (2) Query for Model code (Option Report) | ||
172 | * (3) Query for ODM code (Option Report) | ||
173 | * (4) Query for firmware (Option Report) | ||
174 | * (5) Query for GetXExtension (Option Report) | ||
175 | * (6) Query for GetYExtension (Option Report) | ||
176 | * (7) Query for GetPressureLevels (Option Report) | ||
177 | * (8) SwitchToTablet for Absolute coordinates, or | ||
178 | * SwitchToMouse for Relative coordinates (Command) | ||
179 | * (9) EnableMacroKeys (Command) | ||
180 | * (10) FilterOn (Command) | ||
181 | * (11) AutoGainOn (Command) | ||
182 | * | ||
183 | * (Step 9 can be omitted, but you'll then have no function keys.) | ||
184 | */ | ||
185 | |||
186 | #define USB_VENDOR_ID_AIPTEK 0x08ca | ||
187 | #define USB_REQ_GET_REPORT 0x01 | ||
188 | #define USB_REQ_SET_REPORT 0x09 | ||
189 | |||
190 | /* PointerMode codes | ||
191 | */ | ||
192 | #define AIPTEK_POINTER_ONLY_MOUSE_MODE 0 | ||
193 | #define AIPTEK_POINTER_ONLY_STYLUS_MODE 1 | ||
194 | #define AIPTEK_POINTER_EITHER_MODE 2 | ||
195 | |||
196 | #define AIPTEK_POINTER_ALLOW_MOUSE_MODE(a) \ | ||
197 | (a == AIPTEK_POINTER_ONLY_MOUSE_MODE || \ | ||
198 | a == AIPTEK_POINTER_EITHER_MODE) | ||
199 | #define AIPTEK_POINTER_ALLOW_STYLUS_MODE(a) \ | ||
200 | (a == AIPTEK_POINTER_ONLY_STYLUS_MODE || \ | ||
201 | a == AIPTEK_POINTER_EITHER_MODE) | ||
202 | |||
203 | /* CoordinateMode code | ||
204 | */ | ||
205 | #define AIPTEK_COORDINATE_RELATIVE_MODE 0 | ||
206 | #define AIPTEK_COORDINATE_ABSOLUTE_MODE 1 | ||
207 | |||
208 | /* XTilt and YTilt values | ||
209 | */ | ||
210 | #define AIPTEK_TILT_MIN (-128) | ||
211 | #define AIPTEK_TILT_MAX 127 | ||
212 | #define AIPTEK_TILT_DISABLE (-10101) | ||
213 | |||
214 | /* Wheel values | ||
215 | */ | ||
216 | #define AIPTEK_WHEEL_MIN 0 | ||
217 | #define AIPTEK_WHEEL_MAX 1024 | ||
218 | #define AIPTEK_WHEEL_DISABLE (-10101) | ||
219 | |||
220 | /* ToolCode values, which BTW are 0x140 .. 0x14f | ||
221 | * We have things set up such that if TOOL_BUTTON_FIRED_BIT is | ||
222 | * not set, we'll send one instance of AIPTEK_TOOL_BUTTON_xxx. | ||
223 | * | ||
224 | * Whenever the user resets the value, TOOL_BUTTON_FIRED_BIT will | ||
225 | * get reset. | ||
226 | */ | ||
227 | #define TOOL_BUTTON(x) ((x) & 0x14f) | ||
228 | #define TOOL_BUTTON_FIRED(x) ((x) & 0x200) | ||
229 | #define TOOL_BUTTON_FIRED_BIT 0x200 | ||
230 | /* toolMode codes | ||
231 | */ | ||
232 | #define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN | ||
233 | #define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN | ||
234 | #define AIPTEK_TOOL_BUTTON_PENCIL_MODE BTN_TOOL_PENCIL | ||
235 | #define AIPTEK_TOOL_BUTTON_BRUSH_MODE BTN_TOOL_BRUSH | ||
236 | #define AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE BTN_TOOL_AIRBRUSH | ||
237 | #define AIPTEK_TOOL_BUTTON_ERASER_MODE BTN_TOOL_RUBBER | ||
238 | #define AIPTEK_TOOL_BUTTON_MOUSE_MODE BTN_TOOL_MOUSE | ||
239 | #define AIPTEK_TOOL_BUTTON_LENS_MODE BTN_TOOL_LENS | ||
240 | |||
241 | /* Diagnostic message codes | ||
242 | */ | ||
243 | #define AIPTEK_DIAGNOSTIC_NA 0 | ||
244 | #define AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE 1 | ||
245 | #define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 | ||
246 | #define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 | ||
247 | |||
248 | /* Time to wait (in ms) to help mask hand jittering | ||
249 | * when pressing the stylus buttons. | ||
250 | */ | ||
251 | #define AIPTEK_JITTER_DELAY_DEFAULT 50 | ||
252 | |||
253 | /* Time to wait (in ms) in-between sending the tablet | ||
254 | * a command and beginning the process of reading the return | ||
255 | * sequence from the tablet. | ||
256 | */ | ||
257 | #define AIPTEK_PROGRAMMABLE_DELAY_25 25 | ||
258 | #define AIPTEK_PROGRAMMABLE_DELAY_50 50 | ||
259 | #define AIPTEK_PROGRAMMABLE_DELAY_100 100 | ||
260 | #define AIPTEK_PROGRAMMABLE_DELAY_200 200 | ||
261 | #define AIPTEK_PROGRAMMABLE_DELAY_300 300 | ||
262 | #define AIPTEK_PROGRAMMABLE_DELAY_400 400 | ||
263 | #define AIPTEK_PROGRAMMABLE_DELAY_DEFAULT AIPTEK_PROGRAMMABLE_DELAY_400 | ||
264 | |||
265 | /* Mouse button programming | ||
266 | */ | ||
267 | #define AIPTEK_MOUSE_LEFT_BUTTON 0x01 | ||
268 | #define AIPTEK_MOUSE_RIGHT_BUTTON 0x02 | ||
269 | #define AIPTEK_MOUSE_MIDDLE_BUTTON 0x04 | ||
270 | |||
271 | /* Stylus button programming | ||
272 | */ | ||
273 | #define AIPTEK_STYLUS_LOWER_BUTTON 0x08 | ||
274 | #define AIPTEK_STYLUS_UPPER_BUTTON 0x10 | ||
275 | |||
276 | /* Length of incoming packet from the tablet | ||
277 | */ | ||
278 | #define AIPTEK_PACKET_LENGTH 8 | ||
279 | |||
280 | /* We report in EV_MISC both the proximity and | ||
281 | * whether the report came from the stylus, tablet mouse | ||
282 | * or "unknown" -- Unknown when the tablet is in relative | ||
283 | * mode, because we only get report 1's. | ||
284 | */ | ||
285 | #define AIPTEK_REPORT_TOOL_UNKNOWN 0x10 | ||
286 | #define AIPTEK_REPORT_TOOL_STYLUS 0x20 | ||
287 | #define AIPTEK_REPORT_TOOL_MOUSE 0x40 | ||
288 | |||
289 | static int programmableDelay = AIPTEK_PROGRAMMABLE_DELAY_DEFAULT; | ||
290 | static int jitterDelay = AIPTEK_JITTER_DELAY_DEFAULT; | ||
291 | |||
292 | struct aiptek_features { | ||
293 | int odmCode; /* Tablet manufacturer code */ | ||
294 | int modelCode; /* Tablet model code (not unique) */ | ||
295 | int firmwareCode; /* prom/eeprom version */ | ||
296 | char usbPath[64 + 1]; /* device's physical usb path */ | ||
297 | char inputPath[64 + 1]; /* input device path */ | ||
298 | }; | ||
299 | |||
300 | struct aiptek_settings { | ||
301 | int pointerMode; /* stylus-, mouse-only or either */ | ||
302 | int coordinateMode; /* absolute/relative coords */ | ||
303 | int toolMode; /* pen, pencil, brush, etc. tool */ | ||
304 | int xTilt; /* synthetic xTilt amount */ | ||
305 | int yTilt; /* synthetic yTilt amount */ | ||
306 | int wheel; /* synthetic wheel amount */ | ||
307 | int stylusButtonUpper; /* stylus upper btn delivers... */ | ||
308 | int stylusButtonLower; /* stylus lower btn delivers... */ | ||
309 | int mouseButtonLeft; /* mouse left btn delivers... */ | ||
310 | int mouseButtonMiddle; /* mouse middle btn delivers... */ | ||
311 | int mouseButtonRight; /* mouse right btn delivers... */ | ||
312 | int programmableDelay; /* delay for tablet programming */ | ||
313 | int jitterDelay; /* delay for hand jittering */ | ||
314 | }; | ||
315 | |||
316 | struct aiptek { | ||
317 | struct input_dev *inputdev; /* input device struct */ | ||
318 | struct usb_device *usbdev; /* usb device struct */ | ||
319 | struct urb *urb; /* urb for incoming reports */ | ||
320 | dma_addr_t data_dma; /* our dma stuffage */ | ||
321 | struct aiptek_features features; /* tablet's array of features */ | ||
322 | struct aiptek_settings curSetting; /* tablet's current programmable */ | ||
323 | struct aiptek_settings newSetting; /* ... and new param settings */ | ||
324 | unsigned int ifnum; /* interface number for IO */ | ||
325 | int diagnostic; /* tablet diagnostic codes */ | ||
326 | unsigned long eventCount; /* event count */ | ||
327 | int inDelay; /* jitter: in jitter delay? */ | ||
328 | unsigned long endDelay; /* jitter: time when delay ends */ | ||
329 | int previousJitterable; /* jitterable prev value */ | ||
330 | unsigned char *data; /* incoming packet data */ | ||
331 | }; | ||
332 | |||
333 | /* | ||
334 | * Permit easy lookup of keyboard events to send, versus | ||
335 | * the bitmap which comes from the tablet. This hides the | ||
336 | * issue that the F_keys are not sequentially numbered. | ||
337 | */ | ||
338 | static const int macroKeyEvents[] = { | ||
339 | KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, | ||
340 | KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, | ||
341 | KEY_F12, KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17, | ||
342 | KEY_F18, KEY_F19, KEY_F20, KEY_F21, KEY_F22, KEY_F23, | ||
343 | KEY_F24, KEY_STOP, KEY_AGAIN, KEY_PROPS, KEY_UNDO, | ||
344 | KEY_FRONT, KEY_COPY, KEY_OPEN, KEY_PASTE, 0 | ||
345 | }; | ||
346 | |||
347 | /*********************************************************************** | ||
348 | * Relative reports deliver values in 2's complement format to | ||
349 | * deal with negative offsets. | ||
350 | */ | ||
351 | static int aiptek_convert_from_2s_complement(unsigned char c) | ||
352 | { | ||
353 | int ret; | ||
354 | unsigned char b = c; | ||
355 | int negate = 0; | ||
356 | |||
357 | if ((b & 0x80) != 0) { | ||
358 | b = ~b; | ||
359 | b--; | ||
360 | negate = 1; | ||
361 | } | ||
362 | ret = b; | ||
363 | ret = (negate == 1) ? -ret : ret; | ||
364 | return ret; | ||
365 | } | ||
366 | |||
367 | /*********************************************************************** | ||
368 | * aiptek_irq can receive one of six potential reports. | ||
369 | * The documentation for each is in the body of the function. | ||
370 | * | ||
371 | * The tablet reports on several attributes per invocation of | ||
372 | * aiptek_irq. Because the Linux Input Event system allows the | ||
373 | * transmission of ONE attribute per input_report_xxx() call, | ||
374 | * collation has to be done on the other end to reconstitute | ||
375 | * a complete tablet report. Further, the number of Input Event reports | ||
376 | * submitted varies, depending on what USB report type, and circumstance. | ||
377 | * To deal with this, EV_MSC is used to indicate an 'end-of-report' | ||
378 | * message. This has been an undocumented convention understood by the kernel | ||
379 | * tablet driver and clients such as gpm and XFree86's tablet drivers. | ||
380 | * | ||
381 | * Of the information received from the tablet, the one piece I | ||
382 | * cannot transmit is the proximity bit (without resorting to an EV_MSC | ||
383 | * convention above.) I therefore have taken over REL_MISC and ABS_MISC | ||
384 | * (for relative and absolute reports, respectively) for communicating | ||
385 | * Proximity. Why two events? I thought it interesting to know if the | ||
386 | * Proximity event occurred while the tablet was in absolute or relative | ||
387 | * mode. | ||
388 | * | ||
389 | * Other tablets use the notion of a certain minimum stylus pressure | ||
390 | * to infer proximity. While that could have been done, that is yet | ||
391 | * another 'by convention' behavior, the documentation for which | ||
392 | * would be spread between two (or more) pieces of software. | ||
393 | * | ||
394 | * EV_MSC usage was terminated for this purpose in Linux 2.5.x, and | ||
395 | * replaced with the input_sync() method (which emits EV_SYN.) | ||
396 | */ | ||
397 | |||
398 | static void aiptek_irq(struct urb *urb) | ||
399 | { | ||
400 | struct aiptek *aiptek = urb->context; | ||
401 | unsigned char *data = aiptek->data; | ||
402 | struct input_dev *inputdev = aiptek->inputdev; | ||
403 | int jitterable = 0; | ||
404 | int retval, macro, x, y, z, left, right, middle, p, dv, tip, bs, pck; | ||
405 | |||
406 | switch (urb->status) { | ||
407 | case 0: | ||
408 | /* Success */ | ||
409 | break; | ||
410 | |||
411 | case -ECONNRESET: | ||
412 | case -ENOENT: | ||
413 | case -ESHUTDOWN: | ||
414 | /* This urb is terminated, clean up */ | ||
415 | dbg("%s - urb shutting down with status: %d", | ||
416 | __FUNCTION__, urb->status); | ||
417 | return; | ||
418 | |||
419 | default: | ||
420 | dbg("%s - nonzero urb status received: %d", | ||
421 | __FUNCTION__, urb->status); | ||
422 | goto exit; | ||
423 | } | ||
424 | |||
425 | /* See if we are in a delay loop -- throw out report if true. | ||
426 | */ | ||
427 | if (aiptek->inDelay == 1 && time_after(aiptek->endDelay, jiffies)) { | ||
428 | goto exit; | ||
429 | } | ||
430 | |||
431 | aiptek->inDelay = 0; | ||
432 | aiptek->eventCount++; | ||
433 | |||
434 | /* Report 1 delivers relative coordinates with either a stylus | ||
435 | * or the mouse. You do not know, however, which input | ||
436 | * tool generated the event. | ||
437 | */ | ||
438 | if (data[0] == 1) { | ||
439 | if (aiptek->curSetting.coordinateMode == | ||
440 | AIPTEK_COORDINATE_ABSOLUTE_MODE) { | ||
441 | aiptek->diagnostic = | ||
442 | AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE; | ||
443 | } else { | ||
444 | x = aiptek_convert_from_2s_complement(data[2]); | ||
445 | y = aiptek_convert_from_2s_complement(data[3]); | ||
446 | |||
447 | /* jitterable keeps track of whether any button has been pressed. | ||
448 | * We're also using it to remap the physical mouse button mask | ||
449 | * to pseudo-settings. (We don't specifically care about it's | ||
450 | * value after moving/transposing mouse button bitmasks, except | ||
451 | * that a non-zero value indicates that one or more | ||
452 | * mouse button was pressed.) | ||
453 | */ | ||
454 | jitterable = data[5] & 0x07; | ||
455 | |||
456 | left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; | ||
457 | right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; | ||
458 | middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; | ||
459 | |||
460 | input_report_key(inputdev, BTN_LEFT, left); | ||
461 | input_report_key(inputdev, BTN_MIDDLE, middle); | ||
462 | input_report_key(inputdev, BTN_RIGHT, right); | ||
463 | input_report_rel(inputdev, REL_X, x); | ||
464 | input_report_rel(inputdev, REL_Y, y); | ||
465 | input_report_rel(inputdev, REL_MISC, 1 | AIPTEK_REPORT_TOOL_UNKNOWN); | ||
466 | |||
467 | /* Wheel support is in the form of a single-event | ||
468 | * firing. | ||
469 | */ | ||
470 | if (aiptek->curSetting.wheel != AIPTEK_WHEEL_DISABLE) { | ||
471 | input_report_rel(inputdev, REL_WHEEL, | ||
472 | aiptek->curSetting.wheel); | ||
473 | aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; | ||
474 | } | ||
475 | input_sync(inputdev); | ||
476 | } | ||
477 | } | ||
478 | /* Report 2 is delivered only by the stylus, and delivers | ||
479 | * absolute coordinates. | ||
480 | */ | ||
481 | else if (data[0] == 2) { | ||
482 | if (aiptek->curSetting.coordinateMode == AIPTEK_COORDINATE_RELATIVE_MODE) { | ||
483 | aiptek->diagnostic = AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE; | ||
484 | } else if (!AIPTEK_POINTER_ALLOW_STYLUS_MODE | ||
485 | (aiptek->curSetting.pointerMode)) { | ||
486 | aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED; | ||
487 | } else { | ||
488 | x = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); | ||
489 | y = le16_to_cpu(get_unaligned((__le16 *) (data + 3))); | ||
490 | z = le16_to_cpu(get_unaligned((__le16 *) (data + 6))); | ||
491 | |||
492 | p = (data[5] & 0x01) != 0 ? 1 : 0; | ||
493 | dv = (data[5] & 0x02) != 0 ? 1 : 0; | ||
494 | tip = (data[5] & 0x04) != 0 ? 1 : 0; | ||
495 | |||
496 | /* Use jitterable to re-arrange button masks | ||
497 | */ | ||
498 | jitterable = data[5] & 0x18; | ||
499 | |||
500 | bs = (data[5] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0; | ||
501 | pck = (data[5] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0; | ||
502 | |||
503 | /* dv indicates 'data valid' (e.g., the tablet is in sync | ||
504 | * and has delivered a "correct" report) We will ignore | ||
505 | * all 'bad' reports... | ||
506 | */ | ||
507 | if (dv != 0) { | ||
508 | /* If we've not already sent a tool_button_?? code, do | ||
509 | * so now. Then set FIRED_BIT so it won't be resent unless | ||
510 | * the user forces FIRED_BIT off. | ||
511 | */ | ||
512 | if (TOOL_BUTTON_FIRED | ||
513 | (aiptek->curSetting.toolMode) == 0) { | ||
514 | input_report_key(inputdev, | ||
515 | TOOL_BUTTON(aiptek->curSetting.toolMode), | ||
516 | 1); | ||
517 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | ||
518 | } | ||
519 | |||
520 | if (p != 0) { | ||
521 | input_report_abs(inputdev, ABS_X, x); | ||
522 | input_report_abs(inputdev, ABS_Y, y); | ||
523 | input_report_abs(inputdev, ABS_PRESSURE, z); | ||
524 | |||
525 | input_report_key(inputdev, BTN_TOUCH, tip); | ||
526 | input_report_key(inputdev, BTN_STYLUS, bs); | ||
527 | input_report_key(inputdev, BTN_STYLUS2, pck); | ||
528 | |||
529 | if (aiptek->curSetting.xTilt != | ||
530 | AIPTEK_TILT_DISABLE) { | ||
531 | input_report_abs(inputdev, | ||
532 | ABS_TILT_X, | ||
533 | aiptek->curSetting.xTilt); | ||
534 | } | ||
535 | if (aiptek->curSetting.yTilt != AIPTEK_TILT_DISABLE) { | ||
536 | input_report_abs(inputdev, | ||
537 | ABS_TILT_Y, | ||
538 | aiptek->curSetting.yTilt); | ||
539 | } | ||
540 | |||
541 | /* Wheel support is in the form of a single-event | ||
542 | * firing. | ||
543 | */ | ||
544 | if (aiptek->curSetting.wheel != | ||
545 | AIPTEK_WHEEL_DISABLE) { | ||
546 | input_report_abs(inputdev, | ||
547 | ABS_WHEEL, | ||
548 | aiptek->curSetting.wheel); | ||
549 | aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; | ||
550 | } | ||
551 | } | ||
552 | input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_STYLUS); | ||
553 | input_sync(inputdev); | ||
554 | } | ||
555 | } | ||
556 | } | ||
557 | /* Report 3's come from the mouse in absolute mode. | ||
558 | */ | ||
559 | else if (data[0] == 3) { | ||
560 | if (aiptek->curSetting.coordinateMode == AIPTEK_COORDINATE_RELATIVE_MODE) { | ||
561 | aiptek->diagnostic = AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE; | ||
562 | } else if (!AIPTEK_POINTER_ALLOW_MOUSE_MODE | ||
563 | (aiptek->curSetting.pointerMode)) { | ||
564 | aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED; | ||
565 | } else { | ||
566 | x = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); | ||
567 | y = le16_to_cpu(get_unaligned((__le16 *) (data + 3))); | ||
568 | |||
569 | jitterable = data[5] & 0x1c; | ||
570 | |||
571 | p = (data[5] & 0x01) != 0 ? 1 : 0; | ||
572 | dv = (data[5] & 0x02) != 0 ? 1 : 0; | ||
573 | left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; | ||
574 | right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; | ||
575 | middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; | ||
576 | |||
577 | if (dv != 0) { | ||
578 | /* If we've not already sent a tool_button_?? code, do | ||
579 | * so now. Then set FIRED_BIT so it won't be resent unless | ||
580 | * the user forces FIRED_BIT off. | ||
581 | */ | ||
582 | if (TOOL_BUTTON_FIRED | ||
583 | (aiptek->curSetting.toolMode) == 0) { | ||
584 | input_report_key(inputdev, | ||
585 | TOOL_BUTTON(aiptek->curSetting.toolMode), | ||
586 | 1); | ||
587 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | ||
588 | } | ||
589 | |||
590 | if (p != 0) { | ||
591 | input_report_abs(inputdev, ABS_X, x); | ||
592 | input_report_abs(inputdev, ABS_Y, y); | ||
593 | |||
594 | input_report_key(inputdev, BTN_LEFT, left); | ||
595 | input_report_key(inputdev, BTN_MIDDLE, middle); | ||
596 | input_report_key(inputdev, BTN_RIGHT, right); | ||
597 | |||
598 | /* Wheel support is in the form of a single-event | ||
599 | * firing. | ||
600 | */ | ||
601 | if (aiptek->curSetting.wheel != AIPTEK_WHEEL_DISABLE) { | ||
602 | input_report_abs(inputdev, | ||
603 | ABS_WHEEL, | ||
604 | aiptek->curSetting.wheel); | ||
605 | aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; | ||
606 | } | ||
607 | } | ||
608 | input_report_rel(inputdev, REL_MISC, p | AIPTEK_REPORT_TOOL_MOUSE); | ||
609 | input_sync(inputdev); | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | /* Report 4s come from the macro keys when pressed by stylus | ||
614 | */ | ||
615 | else if (data[0] == 4) { | ||
616 | jitterable = data[1] & 0x18; | ||
617 | |||
618 | p = (data[1] & 0x01) != 0 ? 1 : 0; | ||
619 | dv = (data[1] & 0x02) != 0 ? 1 : 0; | ||
620 | tip = (data[1] & 0x04) != 0 ? 1 : 0; | ||
621 | bs = (data[1] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0; | ||
622 | pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0; | ||
623 | |||
624 | macro = data[3]; | ||
625 | z = le16_to_cpu(get_unaligned((__le16 *) (data + 4))); | ||
626 | |||
627 | if (dv != 0) { | ||
628 | /* If we've not already sent a tool_button_?? code, do | ||
629 | * so now. Then set FIRED_BIT so it won't be resent unless | ||
630 | * the user forces FIRED_BIT off. | ||
631 | */ | ||
632 | if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { | ||
633 | input_report_key(inputdev, | ||
634 | TOOL_BUTTON(aiptek->curSetting.toolMode), | ||
635 | 1); | ||
636 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | ||
637 | } | ||
638 | |||
639 | if (p != 0) { | ||
640 | input_report_key(inputdev, BTN_TOUCH, tip); | ||
641 | input_report_key(inputdev, BTN_STYLUS, bs); | ||
642 | input_report_key(inputdev, BTN_STYLUS2, pck); | ||
643 | input_report_abs(inputdev, ABS_PRESSURE, z); | ||
644 | } | ||
645 | |||
646 | /* For safety, we're sending key 'break' codes for the | ||
647 | * neighboring macro keys. | ||
648 | */ | ||
649 | if (macro > 0) { | ||
650 | input_report_key(inputdev, | ||
651 | macroKeyEvents[macro - 1], 0); | ||
652 | } | ||
653 | if (macro < 25) { | ||
654 | input_report_key(inputdev, | ||
655 | macroKeyEvents[macro + 1], 0); | ||
656 | } | ||
657 | input_report_key(inputdev, macroKeyEvents[macro], p); | ||
658 | input_report_abs(inputdev, ABS_MISC, | ||
659 | p | AIPTEK_REPORT_TOOL_STYLUS); | ||
660 | input_sync(inputdev); | ||
661 | } | ||
662 | } | ||
663 | /* Report 5s come from the macro keys when pressed by mouse | ||
664 | */ | ||
665 | else if (data[0] == 5) { | ||
666 | jitterable = data[1] & 0x1c; | ||
667 | |||
668 | p = (data[1] & 0x01) != 0 ? 1 : 0; | ||
669 | dv = (data[1] & 0x02) != 0 ? 1 : 0; | ||
670 | left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; | ||
671 | right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; | ||
672 | middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; | ||
673 | macro = data[3]; | ||
674 | |||
675 | if (dv != 0) { | ||
676 | /* If we've not already sent a tool_button_?? code, do | ||
677 | * so now. Then set FIRED_BIT so it won't be resent unless | ||
678 | * the user forces FIRED_BIT off. | ||
679 | */ | ||
680 | if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { | ||
681 | input_report_key(inputdev, | ||
682 | TOOL_BUTTON(aiptek->curSetting.toolMode), | ||
683 | 1); | ||
684 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | ||
685 | } | ||
686 | |||
687 | if (p != 0) { | ||
688 | input_report_key(inputdev, BTN_LEFT, left); | ||
689 | input_report_key(inputdev, BTN_MIDDLE, middle); | ||
690 | input_report_key(inputdev, BTN_RIGHT, right); | ||
691 | } | ||
692 | |||
693 | /* For safety, we're sending key 'break' codes for the | ||
694 | * neighboring macro keys. | ||
695 | */ | ||
696 | if (macro > 0) { | ||
697 | input_report_key(inputdev, | ||
698 | macroKeyEvents[macro - 1], 0); | ||
699 | } | ||
700 | if (macro < 25) { | ||
701 | input_report_key(inputdev, | ||
702 | macroKeyEvents[macro + 1], 0); | ||
703 | } | ||
704 | |||
705 | input_report_key(inputdev, macroKeyEvents[macro], 1); | ||
706 | input_report_rel(inputdev, ABS_MISC, | ||
707 | p | AIPTEK_REPORT_TOOL_MOUSE); | ||
708 | input_sync(inputdev); | ||
709 | } | ||
710 | } | ||
711 | /* We have no idea which tool can generate a report 6. Theoretically, | ||
712 | * neither need to, having been given reports 4 & 5 for such use. | ||
713 | * However, report 6 is the 'official-looking' report for macroKeys; | ||
714 | * reports 4 & 5 supposively are used to support unnamed, unknown | ||
715 | * hat switches (which just so happen to be the macroKeys.) | ||
716 | */ | ||
717 | else if (data[0] == 6) { | ||
718 | macro = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); | ||
719 | if (macro > 0) { | ||
720 | input_report_key(inputdev, macroKeyEvents[macro - 1], | ||
721 | 0); | ||
722 | } | ||
723 | if (macro < 25) { | ||
724 | input_report_key(inputdev, macroKeyEvents[macro + 1], | ||
725 | 0); | ||
726 | } | ||
727 | |||
728 | /* If we've not already sent a tool_button_?? code, do | ||
729 | * so now. Then set FIRED_BIT so it won't be resent unless | ||
730 | * the user forces FIRED_BIT off. | ||
731 | */ | ||
732 | if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { | ||
733 | input_report_key(inputdev, | ||
734 | TOOL_BUTTON(aiptek->curSetting. | ||
735 | toolMode), 1); | ||
736 | aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; | ||
737 | } | ||
738 | |||
739 | input_report_key(inputdev, macroKeyEvents[macro], 1); | ||
740 | input_report_abs(inputdev, ABS_MISC, | ||
741 | 1 | AIPTEK_REPORT_TOOL_UNKNOWN); | ||
742 | input_sync(inputdev); | ||
743 | } else { | ||
744 | dbg("Unknown report %d", data[0]); | ||
745 | } | ||
746 | |||
747 | /* Jitter may occur when the user presses a button on the stlyus | ||
748 | * or the mouse. What we do to prevent that is wait 'x' milliseconds | ||
749 | * following a 'jitterable' event, which should give the hand some time | ||
750 | * stabilize itself. | ||
751 | * | ||
752 | * We just introduced aiptek->previousJitterable to carry forth the | ||
753 | * notion that jitter occurs when the button state changes from on to off: | ||
754 | * a person drawing, holding a button down is not subject to jittering. | ||
755 | * With that in mind, changing from upper button depressed to lower button | ||
756 | * WILL transition through a jitter delay. | ||
757 | */ | ||
758 | |||
759 | if (aiptek->previousJitterable != jitterable && | ||
760 | aiptek->curSetting.jitterDelay != 0 && aiptek->inDelay != 1) { | ||
761 | aiptek->endDelay = jiffies + | ||
762 | ((aiptek->curSetting.jitterDelay * HZ) / 1000); | ||
763 | aiptek->inDelay = 1; | ||
764 | } | ||
765 | aiptek->previousJitterable = jitterable; | ||
766 | |||
767 | exit: | ||
768 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
769 | if (retval != 0) { | ||
770 | err("%s - usb_submit_urb failed with result %d", | ||
771 | __FUNCTION__, retval); | ||
772 | } | ||
773 | } | ||
774 | |||
775 | /*********************************************************************** | ||
776 | * These are the USB id's known so far. We do not identify them to | ||
777 | * specific Aiptek model numbers, because there has been overlaps, | ||
778 | * use, and reuse of id's in existing models. Certain models have | ||
779 | * been known to use more than one ID, indicative perhaps of | ||
780 | * manufacturing revisions. In any event, we consider these | ||
781 | * IDs to not be model-specific nor unique. | ||
782 | */ | ||
783 | static const struct usb_device_id aiptek_ids[] = { | ||
784 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x01)}, | ||
785 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x10)}, | ||
786 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x20)}, | ||
787 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x21)}, | ||
788 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x22)}, | ||
789 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x23)}, | ||
790 | {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x24)}, | ||
791 | {} | ||
792 | }; | ||
793 | |||
794 | MODULE_DEVICE_TABLE(usb, aiptek_ids); | ||
795 | |||
796 | /*********************************************************************** | ||
797 | * Open an instance of the tablet driver. | ||
798 | */ | ||
799 | static int aiptek_open(struct input_dev *inputdev) | ||
800 | { | ||
801 | struct aiptek *aiptek = input_get_drvdata(inputdev); | ||
802 | |||
803 | aiptek->urb->dev = aiptek->usbdev; | ||
804 | if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) | ||
805 | return -EIO; | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | /*********************************************************************** | ||
811 | * Close an instance of the tablet driver. | ||
812 | */ | ||
813 | static void aiptek_close(struct input_dev *inputdev) | ||
814 | { | ||
815 | struct aiptek *aiptek = input_get_drvdata(inputdev); | ||
816 | |||
817 | usb_kill_urb(aiptek->urb); | ||
818 | } | ||
819 | |||
820 | /*********************************************************************** | ||
821 | * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, | ||
822 | * where they were known as usb_set_report and usb_get_report. | ||
823 | */ | ||
824 | static int | ||
825 | aiptek_set_report(struct aiptek *aiptek, | ||
826 | unsigned char report_type, | ||
827 | unsigned char report_id, void *buffer, int size) | ||
828 | { | ||
829 | return usb_control_msg(aiptek->usbdev, | ||
830 | usb_sndctrlpipe(aiptek->usbdev, 0), | ||
831 | USB_REQ_SET_REPORT, | ||
832 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
833 | USB_DIR_OUT, (report_type << 8) + report_id, | ||
834 | aiptek->ifnum, buffer, size, 5000); | ||
835 | } | ||
836 | |||
837 | static int | ||
838 | aiptek_get_report(struct aiptek *aiptek, | ||
839 | unsigned char report_type, | ||
840 | unsigned char report_id, void *buffer, int size) | ||
841 | { | ||
842 | return usb_control_msg(aiptek->usbdev, | ||
843 | usb_rcvctrlpipe(aiptek->usbdev, 0), | ||
844 | USB_REQ_GET_REPORT, | ||
845 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
846 | USB_DIR_IN, (report_type << 8) + report_id, | ||
847 | aiptek->ifnum, buffer, size, 5000); | ||
848 | } | ||
849 | |||
850 | /*********************************************************************** | ||
851 | * Send a command to the tablet. | ||
852 | */ | ||
853 | static int | ||
854 | aiptek_command(struct aiptek *aiptek, unsigned char command, unsigned char data) | ||
855 | { | ||
856 | const int sizeof_buf = 3 * sizeof(u8); | ||
857 | int ret; | ||
858 | u8 *buf; | ||
859 | |||
860 | buf = kmalloc(sizeof_buf, GFP_KERNEL); | ||
861 | if (!buf) | ||
862 | return -ENOMEM; | ||
863 | |||
864 | buf[0] = 2; | ||
865 | buf[1] = command; | ||
866 | buf[2] = data; | ||
867 | |||
868 | if ((ret = | ||
869 | aiptek_set_report(aiptek, 3, 2, buf, sizeof_buf)) != sizeof_buf) { | ||
870 | dbg("aiptek_program: failed, tried to send: 0x%02x 0x%02x", | ||
871 | command, data); | ||
872 | } | ||
873 | kfree(buf); | ||
874 | return ret < 0 ? ret : 0; | ||
875 | } | ||
876 | |||
877 | /*********************************************************************** | ||
878 | * Retrieve information from the tablet. Querying info is defined as first | ||
879 | * sending the {command,data} sequence as a command, followed by a wait | ||
880 | * (aka, "programmaticDelay") and then a "read" request. | ||
881 | */ | ||
882 | static int | ||
883 | aiptek_query(struct aiptek *aiptek, unsigned char command, unsigned char data) | ||
884 | { | ||
885 | const int sizeof_buf = 3 * sizeof(u8); | ||
886 | int ret; | ||
887 | u8 *buf; | ||
888 | |||
889 | buf = kmalloc(sizeof_buf, GFP_KERNEL); | ||
890 | if (!buf) | ||
891 | return -ENOMEM; | ||
892 | |||
893 | buf[0] = 2; | ||
894 | buf[1] = command; | ||
895 | buf[2] = data; | ||
896 | |||
897 | if (aiptek_command(aiptek, command, data) != 0) { | ||
898 | kfree(buf); | ||
899 | return -EIO; | ||
900 | } | ||
901 | msleep(aiptek->curSetting.programmableDelay); | ||
902 | |||
903 | if ((ret = | ||
904 | aiptek_get_report(aiptek, 3, 2, buf, sizeof_buf)) != sizeof_buf) { | ||
905 | dbg("aiptek_query failed: returned 0x%02x 0x%02x 0x%02x", | ||
906 | buf[0], buf[1], buf[2]); | ||
907 | ret = -EIO; | ||
908 | } else { | ||
909 | ret = le16_to_cpu(get_unaligned((__le16 *) (buf + 1))); | ||
910 | } | ||
911 | kfree(buf); | ||
912 | return ret; | ||
913 | } | ||
914 | |||
915 | /*********************************************************************** | ||
916 | * Program the tablet into either absolute or relative mode. | ||
917 | * We also get information about the tablet's size. | ||
918 | */ | ||
919 | static int aiptek_program_tablet(struct aiptek *aiptek) | ||
920 | { | ||
921 | int ret; | ||
922 | /* Execute Resolution500LPI */ | ||
923 | if ((ret = aiptek_command(aiptek, 0x18, 0x04)) < 0) | ||
924 | return ret; | ||
925 | |||
926 | /* Query getModelCode */ | ||
927 | if ((ret = aiptek_query(aiptek, 0x02, 0x00)) < 0) | ||
928 | return ret; | ||
929 | aiptek->features.modelCode = ret & 0xff; | ||
930 | |||
931 | /* Query getODMCode */ | ||
932 | if ((ret = aiptek_query(aiptek, 0x03, 0x00)) < 0) | ||
933 | return ret; | ||
934 | aiptek->features.odmCode = ret; | ||
935 | |||
936 | /* Query getFirmwareCode */ | ||
937 | if ((ret = aiptek_query(aiptek, 0x04, 0x00)) < 0) | ||
938 | return ret; | ||
939 | aiptek->features.firmwareCode = ret; | ||
940 | |||
941 | /* Query getXextension */ | ||
942 | if ((ret = aiptek_query(aiptek, 0x01, 0x00)) < 0) | ||
943 | return ret; | ||
944 | aiptek->inputdev->absmin[ABS_X] = 0; | ||
945 | aiptek->inputdev->absmax[ABS_X] = ret - 1; | ||
946 | |||
947 | /* Query getYextension */ | ||
948 | if ((ret = aiptek_query(aiptek, 0x01, 0x01)) < 0) | ||
949 | return ret; | ||
950 | aiptek->inputdev->absmin[ABS_Y] = 0; | ||
951 | aiptek->inputdev->absmax[ABS_Y] = ret - 1; | ||
952 | |||
953 | /* Query getPressureLevels */ | ||
954 | if ((ret = aiptek_query(aiptek, 0x08, 0x00)) < 0) | ||
955 | return ret; | ||
956 | aiptek->inputdev->absmin[ABS_PRESSURE] = 0; | ||
957 | aiptek->inputdev->absmax[ABS_PRESSURE] = ret - 1; | ||
958 | |||
959 | /* Depending on whether we are in absolute or relative mode, we will | ||
960 | * do a switchToTablet(absolute) or switchToMouse(relative) command. | ||
961 | */ | ||
962 | if (aiptek->curSetting.coordinateMode == | ||
963 | AIPTEK_COORDINATE_ABSOLUTE_MODE) { | ||
964 | /* Execute switchToTablet */ | ||
965 | if ((ret = aiptek_command(aiptek, 0x10, 0x01)) < 0) { | ||
966 | return ret; | ||
967 | } | ||
968 | } else { | ||
969 | /* Execute switchToMouse */ | ||
970 | if ((ret = aiptek_command(aiptek, 0x10, 0x00)) < 0) { | ||
971 | return ret; | ||
972 | } | ||
973 | } | ||
974 | |||
975 | /* Enable the macro keys */ | ||
976 | if ((ret = aiptek_command(aiptek, 0x11, 0x02)) < 0) | ||
977 | return ret; | ||
978 | #if 0 | ||
979 | /* Execute FilterOn */ | ||
980 | if ((ret = aiptek_command(aiptek, 0x17, 0x00)) < 0) | ||
981 | return ret; | ||
982 | #endif | ||
983 | |||
984 | /* Execute AutoGainOn */ | ||
985 | if ((ret = aiptek_command(aiptek, 0x12, 0xff)) < 0) | ||
986 | return ret; | ||
987 | |||
988 | /* Reset the eventCount, so we track events from last (re)programming | ||
989 | */ | ||
990 | aiptek->diagnostic = AIPTEK_DIAGNOSTIC_NA; | ||
991 | aiptek->eventCount = 0; | ||
992 | |||
993 | return 0; | ||
994 | } | ||
995 | |||
996 | /*********************************************************************** | ||
997 | * Sysfs functions. Sysfs prefers that individually-tunable parameters | ||
998 | * exist in their separate pseudo-files. Summary data that is immutable | ||
999 | * may exist in a singular file so long as you don't define a writeable | ||
1000 | * interface. | ||
1001 | */ | ||
1002 | |||
1003 | /*********************************************************************** | ||
1004 | * support the 'size' file -- display support | ||
1005 | */ | ||
1006 | static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr, char *buf) | ||
1007 | { | ||
1008 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1009 | |||
1010 | if (aiptek == NULL) | ||
1011 | return 0; | ||
1012 | |||
1013 | return snprintf(buf, PAGE_SIZE, "%dx%d\n", | ||
1014 | aiptek->inputdev->absmax[ABS_X] + 1, | ||
1015 | aiptek->inputdev->absmax[ABS_Y] + 1); | ||
1016 | } | ||
1017 | |||
1018 | /* These structs define the sysfs files, param #1 is the name of the | ||
1019 | * file, param 2 is the file permissions, param 3 & 4 are to the | ||
1020 | * output generator and input parser routines. Absence of a routine is | ||
1021 | * permitted -- it only means can't either 'cat' the file, or send data | ||
1022 | * to it. | ||
1023 | */ | ||
1024 | static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL); | ||
1025 | |||
1026 | /*********************************************************************** | ||
1027 | * support routines for the 'product_id' file | ||
1028 | */ | ||
1029 | static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf) | ||
1030 | { | ||
1031 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1032 | |||
1033 | if (aiptek == NULL) | ||
1034 | return 0; | ||
1035 | |||
1036 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", | ||
1037 | aiptek->inputdev->id.product); | ||
1038 | } | ||
1039 | |||
1040 | static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL); | ||
1041 | |||
1042 | /*********************************************************************** | ||
1043 | * support routines for the 'vendor_id' file | ||
1044 | */ | ||
1045 | static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf) | ||
1046 | { | ||
1047 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1048 | |||
1049 | if (aiptek == NULL) | ||
1050 | return 0; | ||
1051 | |||
1052 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor); | ||
1053 | } | ||
1054 | |||
1055 | static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL); | ||
1056 | |||
1057 | /*********************************************************************** | ||
1058 | * support routines for the 'vendor' file | ||
1059 | */ | ||
1060 | static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf) | ||
1061 | { | ||
1062 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1063 | int retval; | ||
1064 | |||
1065 | if (aiptek == NULL) | ||
1066 | return 0; | ||
1067 | |||
1068 | retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer); | ||
1069 | return retval; | ||
1070 | } | ||
1071 | |||
1072 | static DEVICE_ATTR(vendor, S_IRUGO, show_tabletManufacturer, NULL); | ||
1073 | |||
1074 | /*********************************************************************** | ||
1075 | * support routines for the 'product' file | ||
1076 | */ | ||
1077 | static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf) | ||
1078 | { | ||
1079 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1080 | int retval; | ||
1081 | |||
1082 | if (aiptek == NULL) | ||
1083 | return 0; | ||
1084 | |||
1085 | retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product); | ||
1086 | return retval; | ||
1087 | } | ||
1088 | |||
1089 | static DEVICE_ATTR(product, S_IRUGO, show_tabletProduct, NULL); | ||
1090 | |||
1091 | /*********************************************************************** | ||
1092 | * support routines for the 'pointer_mode' file. Note that this file | ||
1093 | * both displays current setting and allows reprogramming. | ||
1094 | */ | ||
1095 | static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf) | ||
1096 | { | ||
1097 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1098 | char *s; | ||
1099 | |||
1100 | if (aiptek == NULL) | ||
1101 | return 0; | ||
1102 | |||
1103 | switch (aiptek->curSetting.pointerMode) { | ||
1104 | case AIPTEK_POINTER_ONLY_STYLUS_MODE: | ||
1105 | s = "stylus"; | ||
1106 | break; | ||
1107 | |||
1108 | case AIPTEK_POINTER_ONLY_MOUSE_MODE: | ||
1109 | s = "mouse"; | ||
1110 | break; | ||
1111 | |||
1112 | case AIPTEK_POINTER_EITHER_MODE: | ||
1113 | s = "either"; | ||
1114 | break; | ||
1115 | |||
1116 | default: | ||
1117 | s = "unknown"; | ||
1118 | break; | ||
1119 | } | ||
1120 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1121 | } | ||
1122 | |||
1123 | static ssize_t | ||
1124 | store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1125 | { | ||
1126 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1127 | if (aiptek == NULL) | ||
1128 | return 0; | ||
1129 | |||
1130 | if (strcmp(buf, "stylus") == 0) { | ||
1131 | aiptek->newSetting.pointerMode = | ||
1132 | AIPTEK_POINTER_ONLY_STYLUS_MODE; | ||
1133 | } else if (strcmp(buf, "mouse") == 0) { | ||
1134 | aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_MOUSE_MODE; | ||
1135 | } else if (strcmp(buf, "either") == 0) { | ||
1136 | aiptek->newSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE; | ||
1137 | } | ||
1138 | return count; | ||
1139 | } | ||
1140 | |||
1141 | static DEVICE_ATTR(pointer_mode, | ||
1142 | S_IRUGO | S_IWUGO, | ||
1143 | show_tabletPointerMode, store_tabletPointerMode); | ||
1144 | |||
1145 | /*********************************************************************** | ||
1146 | * support routines for the 'coordinate_mode' file. Note that this file | ||
1147 | * both displays current setting and allows reprogramming. | ||
1148 | */ | ||
1149 | static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf) | ||
1150 | { | ||
1151 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1152 | char *s; | ||
1153 | |||
1154 | if (aiptek == NULL) | ||
1155 | return 0; | ||
1156 | |||
1157 | switch (aiptek->curSetting.coordinateMode) { | ||
1158 | case AIPTEK_COORDINATE_ABSOLUTE_MODE: | ||
1159 | s = "absolute"; | ||
1160 | break; | ||
1161 | |||
1162 | case AIPTEK_COORDINATE_RELATIVE_MODE: | ||
1163 | s = "relative"; | ||
1164 | break; | ||
1165 | |||
1166 | default: | ||
1167 | s = "unknown"; | ||
1168 | break; | ||
1169 | } | ||
1170 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1171 | } | ||
1172 | |||
1173 | static ssize_t | ||
1174 | store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1175 | { | ||
1176 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1177 | if (aiptek == NULL) | ||
1178 | return 0; | ||
1179 | |||
1180 | if (strcmp(buf, "absolute") == 0) { | ||
1181 | aiptek->newSetting.pointerMode = | ||
1182 | AIPTEK_COORDINATE_ABSOLUTE_MODE; | ||
1183 | } else if (strcmp(buf, "relative") == 0) { | ||
1184 | aiptek->newSetting.pointerMode = | ||
1185 | AIPTEK_COORDINATE_RELATIVE_MODE; | ||
1186 | } | ||
1187 | return count; | ||
1188 | } | ||
1189 | |||
1190 | static DEVICE_ATTR(coordinate_mode, | ||
1191 | S_IRUGO | S_IWUGO, | ||
1192 | show_tabletCoordinateMode, store_tabletCoordinateMode); | ||
1193 | |||
1194 | /*********************************************************************** | ||
1195 | * support routines for the 'tool_mode' file. Note that this file | ||
1196 | * both displays current setting and allows reprogramming. | ||
1197 | */ | ||
1198 | static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf) | ||
1199 | { | ||
1200 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1201 | char *s; | ||
1202 | |||
1203 | if (aiptek == NULL) | ||
1204 | return 0; | ||
1205 | |||
1206 | switch (TOOL_BUTTON(aiptek->curSetting.toolMode)) { | ||
1207 | case AIPTEK_TOOL_BUTTON_MOUSE_MODE: | ||
1208 | s = "mouse"; | ||
1209 | break; | ||
1210 | |||
1211 | case AIPTEK_TOOL_BUTTON_ERASER_MODE: | ||
1212 | s = "eraser"; | ||
1213 | break; | ||
1214 | |||
1215 | case AIPTEK_TOOL_BUTTON_PENCIL_MODE: | ||
1216 | s = "pencil"; | ||
1217 | break; | ||
1218 | |||
1219 | case AIPTEK_TOOL_BUTTON_PEN_MODE: | ||
1220 | s = "pen"; | ||
1221 | break; | ||
1222 | |||
1223 | case AIPTEK_TOOL_BUTTON_BRUSH_MODE: | ||
1224 | s = "brush"; | ||
1225 | break; | ||
1226 | |||
1227 | case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE: | ||
1228 | s = "airbrush"; | ||
1229 | break; | ||
1230 | |||
1231 | case AIPTEK_TOOL_BUTTON_LENS_MODE: | ||
1232 | s = "lens"; | ||
1233 | break; | ||
1234 | |||
1235 | default: | ||
1236 | s = "unknown"; | ||
1237 | break; | ||
1238 | } | ||
1239 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1240 | } | ||
1241 | |||
1242 | static ssize_t | ||
1243 | store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1244 | { | ||
1245 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1246 | if (aiptek == NULL) | ||
1247 | return 0; | ||
1248 | |||
1249 | if (strcmp(buf, "mouse") == 0) { | ||
1250 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_MOUSE_MODE; | ||
1251 | } else if (strcmp(buf, "eraser") == 0) { | ||
1252 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_ERASER_MODE; | ||
1253 | } else if (strcmp(buf, "pencil") == 0) { | ||
1254 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PENCIL_MODE; | ||
1255 | } else if (strcmp(buf, "pen") == 0) { | ||
1256 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE; | ||
1257 | } else if (strcmp(buf, "brush") == 0) { | ||
1258 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_BRUSH_MODE; | ||
1259 | } else if (strcmp(buf, "airbrush") == 0) { | ||
1260 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE; | ||
1261 | } else if (strcmp(buf, "lens") == 0) { | ||
1262 | aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_LENS_MODE; | ||
1263 | } | ||
1264 | |||
1265 | return count; | ||
1266 | } | ||
1267 | |||
1268 | static DEVICE_ATTR(tool_mode, | ||
1269 | S_IRUGO | S_IWUGO, | ||
1270 | show_tabletToolMode, store_tabletToolMode); | ||
1271 | |||
1272 | /*********************************************************************** | ||
1273 | * support routines for the 'xtilt' file. Note that this file | ||
1274 | * both displays current setting and allows reprogramming. | ||
1275 | */ | ||
1276 | static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *attr, char *buf) | ||
1277 | { | ||
1278 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1279 | |||
1280 | if (aiptek == NULL) | ||
1281 | return 0; | ||
1282 | |||
1283 | if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) { | ||
1284 | return snprintf(buf, PAGE_SIZE, "disable\n"); | ||
1285 | } else { | ||
1286 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
1287 | aiptek->curSetting.xTilt); | ||
1288 | } | ||
1289 | } | ||
1290 | |||
1291 | static ssize_t | ||
1292 | store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1293 | { | ||
1294 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1295 | int x; | ||
1296 | |||
1297 | if (aiptek == NULL) | ||
1298 | return 0; | ||
1299 | |||
1300 | if (strcmp(buf, "disable") == 0) { | ||
1301 | aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE; | ||
1302 | } else { | ||
1303 | x = (int)simple_strtol(buf, NULL, 10); | ||
1304 | if (x >= AIPTEK_TILT_MIN && x <= AIPTEK_TILT_MAX) { | ||
1305 | aiptek->newSetting.xTilt = x; | ||
1306 | } | ||
1307 | } | ||
1308 | return count; | ||
1309 | } | ||
1310 | |||
1311 | static DEVICE_ATTR(xtilt, | ||
1312 | S_IRUGO | S_IWUGO, show_tabletXtilt, store_tabletXtilt); | ||
1313 | |||
1314 | /*********************************************************************** | ||
1315 | * support routines for the 'ytilt' file. Note that this file | ||
1316 | * both displays current setting and allows reprogramming. | ||
1317 | */ | ||
1318 | static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *attr, char *buf) | ||
1319 | { | ||
1320 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1321 | |||
1322 | if (aiptek == NULL) | ||
1323 | return 0; | ||
1324 | |||
1325 | if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) { | ||
1326 | return snprintf(buf, PAGE_SIZE, "disable\n"); | ||
1327 | } else { | ||
1328 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
1329 | aiptek->curSetting.yTilt); | ||
1330 | } | ||
1331 | } | ||
1332 | |||
1333 | static ssize_t | ||
1334 | store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1335 | { | ||
1336 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1337 | int y; | ||
1338 | |||
1339 | if (aiptek == NULL) | ||
1340 | return 0; | ||
1341 | |||
1342 | if (strcmp(buf, "disable") == 0) { | ||
1343 | aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE; | ||
1344 | } else { | ||
1345 | y = (int)simple_strtol(buf, NULL, 10); | ||
1346 | if (y >= AIPTEK_TILT_MIN && y <= AIPTEK_TILT_MAX) { | ||
1347 | aiptek->newSetting.yTilt = y; | ||
1348 | } | ||
1349 | } | ||
1350 | return count; | ||
1351 | } | ||
1352 | |||
1353 | static DEVICE_ATTR(ytilt, | ||
1354 | S_IRUGO | S_IWUGO, show_tabletYtilt, store_tabletYtilt); | ||
1355 | |||
1356 | /*********************************************************************** | ||
1357 | * support routines for the 'jitter' file. Note that this file | ||
1358 | * both displays current setting and allows reprogramming. | ||
1359 | */ | ||
1360 | static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribute *attr, char *buf) | ||
1361 | { | ||
1362 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1363 | |||
1364 | if (aiptek == NULL) | ||
1365 | return 0; | ||
1366 | |||
1367 | return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay); | ||
1368 | } | ||
1369 | |||
1370 | static ssize_t | ||
1371 | store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1372 | { | ||
1373 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1374 | |||
1375 | if (aiptek == NULL) | ||
1376 | return 0; | ||
1377 | |||
1378 | aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10); | ||
1379 | return count; | ||
1380 | } | ||
1381 | |||
1382 | static DEVICE_ATTR(jitter, | ||
1383 | S_IRUGO | S_IWUGO, | ||
1384 | show_tabletJitterDelay, store_tabletJitterDelay); | ||
1385 | |||
1386 | /*********************************************************************** | ||
1387 | * support routines for the 'delay' file. Note that this file | ||
1388 | * both displays current setting and allows reprogramming. | ||
1389 | */ | ||
1390 | static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, char *buf) | ||
1391 | { | ||
1392 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1393 | |||
1394 | if (aiptek == NULL) | ||
1395 | return 0; | ||
1396 | |||
1397 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
1398 | aiptek->curSetting.programmableDelay); | ||
1399 | } | ||
1400 | |||
1401 | static ssize_t | ||
1402 | store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1403 | { | ||
1404 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1405 | |||
1406 | if (aiptek == NULL) | ||
1407 | return 0; | ||
1408 | |||
1409 | aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10); | ||
1410 | return count; | ||
1411 | } | ||
1412 | |||
1413 | static DEVICE_ATTR(delay, | ||
1414 | S_IRUGO | S_IWUGO, | ||
1415 | show_tabletProgrammableDelay, store_tabletProgrammableDelay); | ||
1416 | |||
1417 | /*********************************************************************** | ||
1418 | * support routines for the 'input_path' file. Note that this file | ||
1419 | * only displays current setting. | ||
1420 | */ | ||
1421 | static ssize_t show_tabletInputDevice(struct device *dev, struct device_attribute *attr, char *buf) | ||
1422 | { | ||
1423 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1424 | |||
1425 | if (aiptek == NULL) | ||
1426 | return 0; | ||
1427 | |||
1428 | return snprintf(buf, PAGE_SIZE, "/dev/input/%s\n", | ||
1429 | aiptek->features.inputPath); | ||
1430 | } | ||
1431 | |||
1432 | static DEVICE_ATTR(input_path, S_IRUGO, show_tabletInputDevice, NULL); | ||
1433 | |||
1434 | /*********************************************************************** | ||
1435 | * support routines for the 'event_count' file. Note that this file | ||
1436 | * only displays current setting. | ||
1437 | */ | ||
1438 | static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attribute *attr, char *buf) | ||
1439 | { | ||
1440 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1441 | |||
1442 | if (aiptek == NULL) | ||
1443 | return 0; | ||
1444 | |||
1445 | return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount); | ||
1446 | } | ||
1447 | |||
1448 | static DEVICE_ATTR(event_count, S_IRUGO, show_tabletEventsReceived, NULL); | ||
1449 | |||
1450 | /*********************************************************************** | ||
1451 | * support routines for the 'diagnostic' file. Note that this file | ||
1452 | * only displays current setting. | ||
1453 | */ | ||
1454 | static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_attribute *attr, char *buf) | ||
1455 | { | ||
1456 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1457 | char *retMsg; | ||
1458 | |||
1459 | if (aiptek == NULL) | ||
1460 | return 0; | ||
1461 | |||
1462 | switch (aiptek->diagnostic) { | ||
1463 | case AIPTEK_DIAGNOSTIC_NA: | ||
1464 | retMsg = "no errors\n"; | ||
1465 | break; | ||
1466 | |||
1467 | case AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE: | ||
1468 | retMsg = "Error: receiving relative reports\n"; | ||
1469 | break; | ||
1470 | |||
1471 | case AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE: | ||
1472 | retMsg = "Error: receiving absolute reports\n"; | ||
1473 | break; | ||
1474 | |||
1475 | case AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED: | ||
1476 | if (aiptek->curSetting.pointerMode == | ||
1477 | AIPTEK_POINTER_ONLY_MOUSE_MODE) { | ||
1478 | retMsg = "Error: receiving stylus reports\n"; | ||
1479 | } else { | ||
1480 | retMsg = "Error: receiving mouse reports\n"; | ||
1481 | } | ||
1482 | break; | ||
1483 | |||
1484 | default: | ||
1485 | return 0; | ||
1486 | } | ||
1487 | return snprintf(buf, PAGE_SIZE, retMsg); | ||
1488 | } | ||
1489 | |||
1490 | static DEVICE_ATTR(diagnostic, S_IRUGO, show_tabletDiagnosticMessage, NULL); | ||
1491 | |||
1492 | /*********************************************************************** | ||
1493 | * support routines for the 'stylus_upper' file. Note that this file | ||
1494 | * both displays current setting and allows for setting changing. | ||
1495 | */ | ||
1496 | static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf) | ||
1497 | { | ||
1498 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1499 | char *s; | ||
1500 | |||
1501 | if (aiptek == NULL) | ||
1502 | return 0; | ||
1503 | |||
1504 | switch (aiptek->curSetting.stylusButtonUpper) { | ||
1505 | case AIPTEK_STYLUS_UPPER_BUTTON: | ||
1506 | s = "upper"; | ||
1507 | break; | ||
1508 | |||
1509 | case AIPTEK_STYLUS_LOWER_BUTTON: | ||
1510 | s = "lower"; | ||
1511 | break; | ||
1512 | |||
1513 | default: | ||
1514 | s = "unknown"; | ||
1515 | break; | ||
1516 | } | ||
1517 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1518 | } | ||
1519 | |||
1520 | static ssize_t | ||
1521 | store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1522 | { | ||
1523 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1524 | |||
1525 | if (aiptek == NULL) | ||
1526 | return 0; | ||
1527 | |||
1528 | if (strcmp(buf, "upper") == 0) { | ||
1529 | aiptek->newSetting.stylusButtonUpper = | ||
1530 | AIPTEK_STYLUS_UPPER_BUTTON; | ||
1531 | } else if (strcmp(buf, "lower") == 0) { | ||
1532 | aiptek->newSetting.stylusButtonUpper = | ||
1533 | AIPTEK_STYLUS_LOWER_BUTTON; | ||
1534 | } | ||
1535 | return count; | ||
1536 | } | ||
1537 | |||
1538 | static DEVICE_ATTR(stylus_upper, | ||
1539 | S_IRUGO | S_IWUGO, | ||
1540 | show_tabletStylusUpper, store_tabletStylusUpper); | ||
1541 | |||
1542 | /*********************************************************************** | ||
1543 | * support routines for the 'stylus_lower' file. Note that this file | ||
1544 | * both displays current setting and allows for setting changing. | ||
1545 | */ | ||
1546 | static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf) | ||
1547 | { | ||
1548 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1549 | char *s; | ||
1550 | |||
1551 | if (aiptek == NULL) | ||
1552 | return 0; | ||
1553 | |||
1554 | switch (aiptek->curSetting.stylusButtonLower) { | ||
1555 | case AIPTEK_STYLUS_UPPER_BUTTON: | ||
1556 | s = "upper"; | ||
1557 | break; | ||
1558 | |||
1559 | case AIPTEK_STYLUS_LOWER_BUTTON: | ||
1560 | s = "lower"; | ||
1561 | break; | ||
1562 | |||
1563 | default: | ||
1564 | s = "unknown"; | ||
1565 | break; | ||
1566 | } | ||
1567 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1568 | } | ||
1569 | |||
1570 | static ssize_t | ||
1571 | store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1572 | { | ||
1573 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1574 | |||
1575 | if (aiptek == NULL) | ||
1576 | return 0; | ||
1577 | |||
1578 | if (strcmp(buf, "upper") == 0) { | ||
1579 | aiptek->newSetting.stylusButtonLower = | ||
1580 | AIPTEK_STYLUS_UPPER_BUTTON; | ||
1581 | } else if (strcmp(buf, "lower") == 0) { | ||
1582 | aiptek->newSetting.stylusButtonLower = | ||
1583 | AIPTEK_STYLUS_LOWER_BUTTON; | ||
1584 | } | ||
1585 | return count; | ||
1586 | } | ||
1587 | |||
1588 | static DEVICE_ATTR(stylus_lower, | ||
1589 | S_IRUGO | S_IWUGO, | ||
1590 | show_tabletStylusLower, store_tabletStylusLower); | ||
1591 | |||
1592 | /*********************************************************************** | ||
1593 | * support routines for the 'mouse_left' file. Note that this file | ||
1594 | * both displays current setting and allows for setting changing. | ||
1595 | */ | ||
1596 | static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf) | ||
1597 | { | ||
1598 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1599 | char *s; | ||
1600 | |||
1601 | if (aiptek == NULL) | ||
1602 | return 0; | ||
1603 | |||
1604 | switch (aiptek->curSetting.mouseButtonLeft) { | ||
1605 | case AIPTEK_MOUSE_LEFT_BUTTON: | ||
1606 | s = "left"; | ||
1607 | break; | ||
1608 | |||
1609 | case AIPTEK_MOUSE_MIDDLE_BUTTON: | ||
1610 | s = "middle"; | ||
1611 | break; | ||
1612 | |||
1613 | case AIPTEK_MOUSE_RIGHT_BUTTON: | ||
1614 | s = "right"; | ||
1615 | break; | ||
1616 | |||
1617 | default: | ||
1618 | s = "unknown"; | ||
1619 | break; | ||
1620 | } | ||
1621 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1622 | } | ||
1623 | |||
1624 | static ssize_t | ||
1625 | store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1626 | { | ||
1627 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1628 | |||
1629 | if (aiptek == NULL) | ||
1630 | return 0; | ||
1631 | |||
1632 | if (strcmp(buf, "left") == 0) { | ||
1633 | aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON; | ||
1634 | } else if (strcmp(buf, "middle") == 0) { | ||
1635 | aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_MIDDLE_BUTTON; | ||
1636 | } else if (strcmp(buf, "right") == 0) { | ||
1637 | aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_RIGHT_BUTTON; | ||
1638 | } | ||
1639 | return count; | ||
1640 | } | ||
1641 | |||
1642 | static DEVICE_ATTR(mouse_left, | ||
1643 | S_IRUGO | S_IWUGO, | ||
1644 | show_tabletMouseLeft, store_tabletMouseLeft); | ||
1645 | |||
1646 | /*********************************************************************** | ||
1647 | * support routines for the 'mouse_middle' file. Note that this file | ||
1648 | * both displays current setting and allows for setting changing. | ||
1649 | */ | ||
1650 | static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf) | ||
1651 | { | ||
1652 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1653 | char *s; | ||
1654 | |||
1655 | if (aiptek == NULL) | ||
1656 | return 0; | ||
1657 | |||
1658 | switch (aiptek->curSetting.mouseButtonMiddle) { | ||
1659 | case AIPTEK_MOUSE_LEFT_BUTTON: | ||
1660 | s = "left"; | ||
1661 | break; | ||
1662 | |||
1663 | case AIPTEK_MOUSE_MIDDLE_BUTTON: | ||
1664 | s = "middle"; | ||
1665 | break; | ||
1666 | |||
1667 | case AIPTEK_MOUSE_RIGHT_BUTTON: | ||
1668 | s = "right"; | ||
1669 | break; | ||
1670 | |||
1671 | default: | ||
1672 | s = "unknown"; | ||
1673 | break; | ||
1674 | } | ||
1675 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1676 | } | ||
1677 | |||
1678 | static ssize_t | ||
1679 | store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1680 | { | ||
1681 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1682 | |||
1683 | if (aiptek == NULL) | ||
1684 | return 0; | ||
1685 | |||
1686 | if (strcmp(buf, "left") == 0) { | ||
1687 | aiptek->newSetting.mouseButtonMiddle = AIPTEK_MOUSE_LEFT_BUTTON; | ||
1688 | } else if (strcmp(buf, "middle") == 0) { | ||
1689 | aiptek->newSetting.mouseButtonMiddle = | ||
1690 | AIPTEK_MOUSE_MIDDLE_BUTTON; | ||
1691 | } else if (strcmp(buf, "right") == 0) { | ||
1692 | aiptek->newSetting.mouseButtonMiddle = | ||
1693 | AIPTEK_MOUSE_RIGHT_BUTTON; | ||
1694 | } | ||
1695 | return count; | ||
1696 | } | ||
1697 | |||
1698 | static DEVICE_ATTR(mouse_middle, | ||
1699 | S_IRUGO | S_IWUGO, | ||
1700 | show_tabletMouseMiddle, store_tabletMouseMiddle); | ||
1701 | |||
1702 | /*********************************************************************** | ||
1703 | * support routines for the 'mouse_right' file. Note that this file | ||
1704 | * both displays current setting and allows for setting changing. | ||
1705 | */ | ||
1706 | static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf) | ||
1707 | { | ||
1708 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1709 | char *s; | ||
1710 | |||
1711 | if (aiptek == NULL) | ||
1712 | return 0; | ||
1713 | |||
1714 | switch (aiptek->curSetting.mouseButtonRight) { | ||
1715 | case AIPTEK_MOUSE_LEFT_BUTTON: | ||
1716 | s = "left"; | ||
1717 | break; | ||
1718 | |||
1719 | case AIPTEK_MOUSE_MIDDLE_BUTTON: | ||
1720 | s = "middle"; | ||
1721 | break; | ||
1722 | |||
1723 | case AIPTEK_MOUSE_RIGHT_BUTTON: | ||
1724 | s = "right"; | ||
1725 | break; | ||
1726 | |||
1727 | default: | ||
1728 | s = "unknown"; | ||
1729 | break; | ||
1730 | } | ||
1731 | return snprintf(buf, PAGE_SIZE, "%s\n", s); | ||
1732 | } | ||
1733 | |||
1734 | static ssize_t | ||
1735 | store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1736 | { | ||
1737 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1738 | |||
1739 | if (aiptek == NULL) | ||
1740 | return 0; | ||
1741 | |||
1742 | if (strcmp(buf, "left") == 0) { | ||
1743 | aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_LEFT_BUTTON; | ||
1744 | } else if (strcmp(buf, "middle") == 0) { | ||
1745 | aiptek->newSetting.mouseButtonRight = | ||
1746 | AIPTEK_MOUSE_MIDDLE_BUTTON; | ||
1747 | } else if (strcmp(buf, "right") == 0) { | ||
1748 | aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON; | ||
1749 | } | ||
1750 | return count; | ||
1751 | } | ||
1752 | |||
1753 | static DEVICE_ATTR(mouse_right, | ||
1754 | S_IRUGO | S_IWUGO, | ||
1755 | show_tabletMouseRight, store_tabletMouseRight); | ||
1756 | |||
1757 | /*********************************************************************** | ||
1758 | * support routines for the 'wheel' file. Note that this file | ||
1759 | * both displays current setting and allows for setting changing. | ||
1760 | */ | ||
1761 | static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *attr, char *buf) | ||
1762 | { | ||
1763 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1764 | |||
1765 | if (aiptek == NULL) | ||
1766 | return 0; | ||
1767 | |||
1768 | if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) { | ||
1769 | return snprintf(buf, PAGE_SIZE, "disable\n"); | ||
1770 | } else { | ||
1771 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
1772 | aiptek->curSetting.wheel); | ||
1773 | } | ||
1774 | } | ||
1775 | |||
1776 | static ssize_t | ||
1777 | store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1778 | { | ||
1779 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1780 | |||
1781 | if (aiptek == NULL) | ||
1782 | return 0; | ||
1783 | |||
1784 | aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10); | ||
1785 | return count; | ||
1786 | } | ||
1787 | |||
1788 | static DEVICE_ATTR(wheel, | ||
1789 | S_IRUGO | S_IWUGO, show_tabletWheel, store_tabletWheel); | ||
1790 | |||
1791 | /*********************************************************************** | ||
1792 | * support routines for the 'execute' file. Note that this file | ||
1793 | * both displays current setting and allows for setting changing. | ||
1794 | */ | ||
1795 | static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf) | ||
1796 | { | ||
1797 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1798 | |||
1799 | if (aiptek == NULL) | ||
1800 | return 0; | ||
1801 | |||
1802 | /* There is nothing useful to display, so a one-line manual | ||
1803 | * is in order... | ||
1804 | */ | ||
1805 | return snprintf(buf, PAGE_SIZE, | ||
1806 | "Write anything to this file to program your tablet.\n"); | ||
1807 | } | ||
1808 | |||
1809 | static ssize_t | ||
1810 | store_tabletExecute(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1811 | { | ||
1812 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1813 | |||
1814 | if (aiptek == NULL) | ||
1815 | return 0; | ||
1816 | |||
1817 | /* We do not care what you write to this file. Merely the action | ||
1818 | * of writing to this file triggers a tablet reprogramming. | ||
1819 | */ | ||
1820 | memcpy(&aiptek->curSetting, &aiptek->newSetting, | ||
1821 | sizeof(struct aiptek_settings)); | ||
1822 | |||
1823 | if (aiptek_program_tablet(aiptek) < 0) | ||
1824 | return -EIO; | ||
1825 | |||
1826 | return count; | ||
1827 | } | ||
1828 | |||
1829 | static DEVICE_ATTR(execute, | ||
1830 | S_IRUGO | S_IWUGO, show_tabletExecute, store_tabletExecute); | ||
1831 | |||
1832 | /*********************************************************************** | ||
1833 | * support routines for the 'odm_code' file. Note that this file | ||
1834 | * only displays current setting. | ||
1835 | */ | ||
1836 | static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *attr, char *buf) | ||
1837 | { | ||
1838 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1839 | |||
1840 | if (aiptek == NULL) | ||
1841 | return 0; | ||
1842 | |||
1843 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode); | ||
1844 | } | ||
1845 | |||
1846 | static DEVICE_ATTR(odm_code, S_IRUGO, show_tabletODMCode, NULL); | ||
1847 | |||
1848 | /*********************************************************************** | ||
1849 | * support routines for the 'model_code' file. Note that this file | ||
1850 | * only displays current setting. | ||
1851 | */ | ||
1852 | static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute *attr, char *buf) | ||
1853 | { | ||
1854 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1855 | |||
1856 | if (aiptek == NULL) | ||
1857 | return 0; | ||
1858 | |||
1859 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode); | ||
1860 | } | ||
1861 | |||
1862 | static DEVICE_ATTR(model_code, S_IRUGO, show_tabletModelCode, NULL); | ||
1863 | |||
1864 | /*********************************************************************** | ||
1865 | * support routines for the 'firmware_code' file. Note that this file | ||
1866 | * only displays current setting. | ||
1867 | */ | ||
1868 | static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *attr, char *buf) | ||
1869 | { | ||
1870 | struct aiptek *aiptek = dev_get_drvdata(dev); | ||
1871 | |||
1872 | if (aiptek == NULL) | ||
1873 | return 0; | ||
1874 | |||
1875 | return snprintf(buf, PAGE_SIZE, "%04x\n", | ||
1876 | aiptek->features.firmwareCode); | ||
1877 | } | ||
1878 | |||
1879 | static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL); | ||
1880 | |||
1881 | /*********************************************************************** | ||
1882 | * This routine removes all existing sysfs files managed by this device | ||
1883 | * driver. | ||
1884 | */ | ||
1885 | static void aiptek_delete_files(struct device *dev) | ||
1886 | { | ||
1887 | device_remove_file(dev, &dev_attr_size); | ||
1888 | device_remove_file(dev, &dev_attr_product_id); | ||
1889 | device_remove_file(dev, &dev_attr_vendor_id); | ||
1890 | device_remove_file(dev, &dev_attr_vendor); | ||
1891 | device_remove_file(dev, &dev_attr_product); | ||
1892 | device_remove_file(dev, &dev_attr_pointer_mode); | ||
1893 | device_remove_file(dev, &dev_attr_coordinate_mode); | ||
1894 | device_remove_file(dev, &dev_attr_tool_mode); | ||
1895 | device_remove_file(dev, &dev_attr_xtilt); | ||
1896 | device_remove_file(dev, &dev_attr_ytilt); | ||
1897 | device_remove_file(dev, &dev_attr_jitter); | ||
1898 | device_remove_file(dev, &dev_attr_delay); | ||
1899 | device_remove_file(dev, &dev_attr_input_path); | ||
1900 | device_remove_file(dev, &dev_attr_event_count); | ||
1901 | device_remove_file(dev, &dev_attr_diagnostic); | ||
1902 | device_remove_file(dev, &dev_attr_odm_code); | ||
1903 | device_remove_file(dev, &dev_attr_model_code); | ||
1904 | device_remove_file(dev, &dev_attr_firmware_code); | ||
1905 | device_remove_file(dev, &dev_attr_stylus_lower); | ||
1906 | device_remove_file(dev, &dev_attr_stylus_upper); | ||
1907 | device_remove_file(dev, &dev_attr_mouse_left); | ||
1908 | device_remove_file(dev, &dev_attr_mouse_middle); | ||
1909 | device_remove_file(dev, &dev_attr_mouse_right); | ||
1910 | device_remove_file(dev, &dev_attr_wheel); | ||
1911 | device_remove_file(dev, &dev_attr_execute); | ||
1912 | } | ||
1913 | |||
1914 | /*********************************************************************** | ||
1915 | * This routine creates the sysfs files managed by this device | ||
1916 | * driver. | ||
1917 | */ | ||
1918 | static int aiptek_add_files(struct device *dev) | ||
1919 | { | ||
1920 | int ret; | ||
1921 | |||
1922 | if ((ret = device_create_file(dev, &dev_attr_size)) || | ||
1923 | (ret = device_create_file(dev, &dev_attr_product_id)) || | ||
1924 | (ret = device_create_file(dev, &dev_attr_vendor_id)) || | ||
1925 | (ret = device_create_file(dev, &dev_attr_vendor)) || | ||
1926 | (ret = device_create_file(dev, &dev_attr_product)) || | ||
1927 | (ret = device_create_file(dev, &dev_attr_pointer_mode)) || | ||
1928 | (ret = device_create_file(dev, &dev_attr_coordinate_mode)) || | ||
1929 | (ret = device_create_file(dev, &dev_attr_tool_mode)) || | ||
1930 | (ret = device_create_file(dev, &dev_attr_xtilt)) || | ||
1931 | (ret = device_create_file(dev, &dev_attr_ytilt)) || | ||
1932 | (ret = device_create_file(dev, &dev_attr_jitter)) || | ||
1933 | (ret = device_create_file(dev, &dev_attr_delay)) || | ||
1934 | (ret = device_create_file(dev, &dev_attr_input_path)) || | ||
1935 | (ret = device_create_file(dev, &dev_attr_event_count)) || | ||
1936 | (ret = device_create_file(dev, &dev_attr_diagnostic)) || | ||
1937 | (ret = device_create_file(dev, &dev_attr_odm_code)) || | ||
1938 | (ret = device_create_file(dev, &dev_attr_model_code)) || | ||
1939 | (ret = device_create_file(dev, &dev_attr_firmware_code)) || | ||
1940 | (ret = device_create_file(dev, &dev_attr_stylus_lower)) || | ||
1941 | (ret = device_create_file(dev, &dev_attr_stylus_upper)) || | ||
1942 | (ret = device_create_file(dev, &dev_attr_mouse_left)) || | ||
1943 | (ret = device_create_file(dev, &dev_attr_mouse_middle)) || | ||
1944 | (ret = device_create_file(dev, &dev_attr_mouse_right)) || | ||
1945 | (ret = device_create_file(dev, &dev_attr_wheel)) || | ||
1946 | (ret = device_create_file(dev, &dev_attr_execute))) { | ||
1947 | err("aiptek: killing own sysfs device files\n"); | ||
1948 | aiptek_delete_files(dev); | ||
1949 | } | ||
1950 | return ret; | ||
1951 | } | ||
1952 | |||
1953 | /*********************************************************************** | ||
1954 | * This routine is called when a tablet has been identified. It basically | ||
1955 | * sets up the tablet and the driver's internal structures. | ||
1956 | */ | ||
1957 | static int | ||
1958 | aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
1959 | { | ||
1960 | struct usb_device *usbdev = interface_to_usbdev(intf); | ||
1961 | struct usb_endpoint_descriptor *endpoint; | ||
1962 | struct aiptek *aiptek; | ||
1963 | struct input_dev *inputdev; | ||
1964 | struct input_handle *inputhandle; | ||
1965 | struct list_head *node, *next; | ||
1966 | int i; | ||
1967 | int speeds[] = { 0, | ||
1968 | AIPTEK_PROGRAMMABLE_DELAY_50, | ||
1969 | AIPTEK_PROGRAMMABLE_DELAY_400, | ||
1970 | AIPTEK_PROGRAMMABLE_DELAY_25, | ||
1971 | AIPTEK_PROGRAMMABLE_DELAY_100, | ||
1972 | AIPTEK_PROGRAMMABLE_DELAY_200, | ||
1973 | AIPTEK_PROGRAMMABLE_DELAY_300 | ||
1974 | }; | ||
1975 | int err = -ENOMEM; | ||
1976 | |||
1977 | /* programmableDelay is where the command-line specified | ||
1978 | * delay is kept. We make it the first element of speeds[], | ||
1979 | * so therefore, your override speed is tried first, then the | ||
1980 | * remainder. Note that the default value of 400ms will be tried | ||
1981 | * if you do not specify any command line parameter. | ||
1982 | */ | ||
1983 | speeds[0] = programmableDelay; | ||
1984 | |||
1985 | aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL); | ||
1986 | inputdev = input_allocate_device(); | ||
1987 | if (!aiptek || !inputdev) | ||
1988 | goto fail1; | ||
1989 | |||
1990 | aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH, | ||
1991 | GFP_ATOMIC, &aiptek->data_dma); | ||
1992 | if (!aiptek->data) | ||
1993 | goto fail1; | ||
1994 | |||
1995 | aiptek->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1996 | if (!aiptek->urb) | ||
1997 | goto fail2; | ||
1998 | |||
1999 | aiptek->inputdev = inputdev; | ||
2000 | aiptek->usbdev = usbdev; | ||
2001 | aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber; | ||
2002 | aiptek->inDelay = 0; | ||
2003 | aiptek->endDelay = 0; | ||
2004 | aiptek->previousJitterable = 0; | ||
2005 | |||
2006 | /* Set up the curSettings struct. Said struct contains the current | ||
2007 | * programmable parameters. The newSetting struct contains changes | ||
2008 | * the user makes to the settings via the sysfs interface. Those | ||
2009 | * changes are not "committed" to curSettings until the user | ||
2010 | * writes to the sysfs/.../execute file. | ||
2011 | */ | ||
2012 | aiptek->curSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE; | ||
2013 | aiptek->curSetting.coordinateMode = AIPTEK_COORDINATE_ABSOLUTE_MODE; | ||
2014 | aiptek->curSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE; | ||
2015 | aiptek->curSetting.xTilt = AIPTEK_TILT_DISABLE; | ||
2016 | aiptek->curSetting.yTilt = AIPTEK_TILT_DISABLE; | ||
2017 | aiptek->curSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON; | ||
2018 | aiptek->curSetting.mouseButtonMiddle = AIPTEK_MOUSE_MIDDLE_BUTTON; | ||
2019 | aiptek->curSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON; | ||
2020 | aiptek->curSetting.stylusButtonUpper = AIPTEK_STYLUS_UPPER_BUTTON; | ||
2021 | aiptek->curSetting.stylusButtonLower = AIPTEK_STYLUS_LOWER_BUTTON; | ||
2022 | aiptek->curSetting.jitterDelay = jitterDelay; | ||
2023 | aiptek->curSetting.programmableDelay = programmableDelay; | ||
2024 | |||
2025 | /* Both structs should have equivalent settings | ||
2026 | */ | ||
2027 | aiptek->newSetting = aiptek->curSetting; | ||
2028 | |||
2029 | /* Determine the usb devices' physical path. | ||
2030 | * Asketh not why we always pretend we're using "../input0", | ||
2031 | * but I suspect this will have to be refactored one | ||
2032 | * day if a single USB device can be a keyboard & a mouse | ||
2033 | * & a tablet, and the inputX number actually will tell | ||
2034 | * us something... | ||
2035 | */ | ||
2036 | usb_make_path(usbdev, aiptek->features.usbPath, | ||
2037 | sizeof(aiptek->features.usbPath)); | ||
2038 | strlcat(aiptek->features.usbPath, "/input0", | ||
2039 | sizeof(aiptek->features.usbPath)); | ||
2040 | |||
2041 | /* Set up client data, pointers to open and close routines | ||
2042 | * for the input device. | ||
2043 | */ | ||
2044 | inputdev->name = "Aiptek"; | ||
2045 | inputdev->phys = aiptek->features.usbPath; | ||
2046 | usb_to_input_id(usbdev, &inputdev->id); | ||
2047 | inputdev->dev.parent = &intf->dev; | ||
2048 | |||
2049 | input_set_drvdata(inputdev, aiptek); | ||
2050 | |||
2051 | inputdev->open = aiptek_open; | ||
2052 | inputdev->close = aiptek_close; | ||
2053 | |||
2054 | /* Now program the capacities of the tablet, in terms of being | ||
2055 | * an input device. | ||
2056 | */ | ||
2057 | inputdev->evbit[0] |= BIT(EV_KEY) | ||
2058 | | BIT(EV_ABS) | ||
2059 | | BIT(EV_REL) | ||
2060 | | BIT(EV_MSC); | ||
2061 | |||
2062 | inputdev->absbit[0] |= BIT(ABS_MISC); | ||
2063 | |||
2064 | inputdev->relbit[0] |= | ||
2065 | (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC)); | ||
2066 | |||
2067 | inputdev->keybit[LONG(BTN_LEFT)] |= | ||
2068 | (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE)); | ||
2069 | |||
2070 | inputdev->keybit[LONG(BTN_DIGI)] |= | ||
2071 | (BIT(BTN_TOOL_PEN) | | ||
2072 | BIT(BTN_TOOL_RUBBER) | | ||
2073 | BIT(BTN_TOOL_PENCIL) | | ||
2074 | BIT(BTN_TOOL_AIRBRUSH) | | ||
2075 | BIT(BTN_TOOL_BRUSH) | | ||
2076 | BIT(BTN_TOOL_MOUSE) | | ||
2077 | BIT(BTN_TOOL_LENS) | | ||
2078 | BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2)); | ||
2079 | |||
2080 | inputdev->mscbit[0] = BIT(MSC_SERIAL); | ||
2081 | |||
2082 | /* Programming the tablet macro keys needs to be done with a for loop | ||
2083 | * as the keycodes are discontiguous. | ||
2084 | */ | ||
2085 | for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i) | ||
2086 | set_bit(macroKeyEvents[i], inputdev->keybit); | ||
2087 | |||
2088 | /* | ||
2089 | * Program the input device coordinate capacities. We do not yet | ||
2090 | * know what maximum X, Y, and Z values are, so we're putting fake | ||
2091 | * values in. Later, we'll ask the tablet to put in the correct | ||
2092 | * values. | ||
2093 | */ | ||
2094 | input_set_abs_params(inputdev, ABS_X, 0, 2999, 0, 0); | ||
2095 | input_set_abs_params(inputdev, ABS_Y, 0, 2249, 0, 0); | ||
2096 | input_set_abs_params(inputdev, ABS_PRESSURE, 0, 511, 0, 0); | ||
2097 | input_set_abs_params(inputdev, ABS_TILT_X, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0); | ||
2098 | input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0); | ||
2099 | input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0); | ||
2100 | |||
2101 | endpoint = &intf->altsetting[0].endpoint[0].desc; | ||
2102 | |||
2103 | /* Go set up our URB, which is called when the tablet receives | ||
2104 | * input. | ||
2105 | */ | ||
2106 | usb_fill_int_urb(aiptek->urb, | ||
2107 | aiptek->usbdev, | ||
2108 | usb_rcvintpipe(aiptek->usbdev, | ||
2109 | endpoint->bEndpointAddress), | ||
2110 | aiptek->data, 8, aiptek_irq, aiptek, | ||
2111 | endpoint->bInterval); | ||
2112 | |||
2113 | aiptek->urb->transfer_dma = aiptek->data_dma; | ||
2114 | aiptek->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
2115 | |||
2116 | /* Program the tablet. This sets the tablet up in the mode | ||
2117 | * specified in newSetting, and also queries the tablet's | ||
2118 | * physical capacities. | ||
2119 | * | ||
2120 | * Sanity check: if a tablet doesn't like the slow programmatic | ||
2121 | * delay, we often get sizes of 0x0. Let's use that as an indicator | ||
2122 | * to try faster delays, up to 25 ms. If that logic fails, well, you'll | ||
2123 | * have to explain to us how your tablet thinks it's 0x0, and yet that's | ||
2124 | * not an error :-) | ||
2125 | */ | ||
2126 | |||
2127 | for (i = 0; i < ARRAY_SIZE(speeds); ++i) { | ||
2128 | aiptek->curSetting.programmableDelay = speeds[i]; | ||
2129 | (void)aiptek_program_tablet(aiptek); | ||
2130 | if (aiptek->inputdev->absmax[ABS_X] > 0) { | ||
2131 | info("input: Aiptek using %d ms programming speed\n", | ||
2132 | aiptek->curSetting.programmableDelay); | ||
2133 | break; | ||
2134 | } | ||
2135 | } | ||
2136 | |||
2137 | /* Register the tablet as an Input Device | ||
2138 | */ | ||
2139 | err = input_register_device(aiptek->inputdev); | ||
2140 | if (err) | ||
2141 | goto fail2; | ||
2142 | |||
2143 | /* We now will look for the evdev device which is mapped to | ||
2144 | * the tablet. The partial name is kept in the link list of | ||
2145 | * input_handles associated with this input device. | ||
2146 | * What identifies an evdev input_handler is that it begins | ||
2147 | * with 'event', continues with a digit, and that in turn | ||
2148 | * is mapped to input/eventN. | ||
2149 | */ | ||
2150 | list_for_each_safe(node, next, &inputdev->h_list) { | ||
2151 | inputhandle = to_handle(node); | ||
2152 | if (strncmp(inputhandle->name, "event", 5) == 0) { | ||
2153 | strcpy(aiptek->features.inputPath, inputhandle->name); | ||
2154 | break; | ||
2155 | } | ||
2156 | } | ||
2157 | |||
2158 | /* Associate this driver's struct with the usb interface. | ||
2159 | */ | ||
2160 | usb_set_intfdata(intf, aiptek); | ||
2161 | |||
2162 | /* Set up the sysfs files | ||
2163 | */ | ||
2164 | aiptek_add_files(&intf->dev); | ||
2165 | |||
2166 | /* Make sure the evdev module is loaded. Assuming evdev IS a module :-) | ||
2167 | */ | ||
2168 | if (request_module("evdev") != 0) | ||
2169 | info("aiptek: error loading 'evdev' module"); | ||
2170 | |||
2171 | return 0; | ||
2172 | |||
2173 | fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, | ||
2174 | aiptek->data_dma); | ||
2175 | fail1: input_free_device(inputdev); | ||
2176 | kfree(aiptek); | ||
2177 | return err; | ||
2178 | } | ||
2179 | |||
2180 | /*********************************************************************** | ||
2181 | * Deal with tablet disconnecting from the system. | ||
2182 | */ | ||
2183 | static void aiptek_disconnect(struct usb_interface *intf) | ||
2184 | { | ||
2185 | struct aiptek *aiptek = usb_get_intfdata(intf); | ||
2186 | |||
2187 | /* Disassociate driver's struct with usb interface | ||
2188 | */ | ||
2189 | usb_set_intfdata(intf, NULL); | ||
2190 | if (aiptek != NULL) { | ||
2191 | /* Free & unhook everything from the system. | ||
2192 | */ | ||
2193 | usb_kill_urb(aiptek->urb); | ||
2194 | input_unregister_device(aiptek->inputdev); | ||
2195 | aiptek_delete_files(&intf->dev); | ||
2196 | usb_free_urb(aiptek->urb); | ||
2197 | usb_buffer_free(interface_to_usbdev(intf), | ||
2198 | AIPTEK_PACKET_LENGTH, | ||
2199 | aiptek->data, aiptek->data_dma); | ||
2200 | kfree(aiptek); | ||
2201 | } | ||
2202 | } | ||
2203 | |||
2204 | static struct usb_driver aiptek_driver = { | ||
2205 | .name = "aiptek", | ||
2206 | .probe = aiptek_probe, | ||
2207 | .disconnect = aiptek_disconnect, | ||
2208 | .id_table = aiptek_ids, | ||
2209 | }; | ||
2210 | |||
2211 | static int __init aiptek_init(void) | ||
2212 | { | ||
2213 | int result = usb_register(&aiptek_driver); | ||
2214 | if (result == 0) { | ||
2215 | info(DRIVER_VERSION ": " DRIVER_AUTHOR); | ||
2216 | info(DRIVER_DESC); | ||
2217 | } | ||
2218 | return result; | ||
2219 | } | ||
2220 | |||
2221 | static void __exit aiptek_exit(void) | ||
2222 | { | ||
2223 | usb_deregister(&aiptek_driver); | ||
2224 | } | ||
2225 | |||
2226 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
2227 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
2228 | MODULE_LICENSE("GPL"); | ||
2229 | |||
2230 | module_param(programmableDelay, int, 0); | ||
2231 | MODULE_PARM_DESC(programmableDelay, "delay used during tablet programming"); | ||
2232 | module_param(jitterDelay, int, 0); | ||
2233 | MODULE_PARM_DESC(jitterDelay, "stylus/mouse settlement delay"); | ||
2234 | |||
2235 | module_init(aiptek_init); | ||
2236 | module_exit(aiptek_exit); | ||
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c new file mode 100644 index 000000000000..b2ca10f2fe0e --- /dev/null +++ b/drivers/input/tablet/gtco.c | |||
@@ -0,0 +1,1055 @@ | |||
1 | /* -*- linux-c -*- | ||
2 | |||
3 | GTCO digitizer USB driver | ||
4 | |||
5 | Use the err(), dbg() and info() macros from usb.h for system logging | ||
6 | |||
7 | TO CHECK: Is pressure done right on report 5? | ||
8 | |||
9 | Copyright (C) 2006 GTCO CalComp | ||
10 | |||
11 | This program is free software; you can redistribute it and/or | ||
12 | modify it under the terms of the GNU General Public License | ||
13 | as published by the Free Software Foundation; version 2 | ||
14 | of the License. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | GNU General Public License for more details. | ||
20 | |||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
24 | |||
25 | Permission to use, copy, modify, distribute, and sell this software and its | ||
26 | documentation for any purpose is hereby granted without fee, provided that | ||
27 | the above copyright notice appear in all copies and that both that | ||
28 | copyright notice and this permission notice appear in supporting | ||
29 | documentation, and that the name of GTCO-CalComp not be used in advertising | ||
30 | or publicity pertaining to distribution of the software without specific, | ||
31 | written prior permission. GTCO-CalComp makes no representations about the | ||
32 | suitability of this software for any purpose. It is provided "as is" | ||
33 | without express or implied warranty. | ||
34 | |||
35 | GTCO-CALCOMP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
36 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
37 | EVENT SHALL GTCO-CALCOMP BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
38 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
39 | DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
40 | TORTIOUS ACTIONS, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
41 | PERFORMANCE OF THIS SOFTWARE. | ||
42 | |||
43 | GTCO CalComp, Inc. | ||
44 | 7125 Riverwood Drive | ||
45 | Columbia, MD 21046 | ||
46 | |||
47 | Jeremy Roberson jroberson@gtcocalcomp.com | ||
48 | Scott Hill shill@gtcocalcomp.com | ||
49 | */ | ||
50 | |||
51 | |||
52 | |||
53 | /*#define DEBUG*/ | ||
54 | |||
55 | #include <linux/kernel.h> | ||
56 | #include <linux/module.h> | ||
57 | #include <linux/errno.h> | ||
58 | #include <linux/init.h> | ||
59 | #include <linux/slab.h> | ||
60 | #include <linux/input.h> | ||
61 | #include <linux/usb.h> | ||
62 | #include <asm/uaccess.h> | ||
63 | #include <asm/unaligned.h> | ||
64 | #include <asm/byteorder.h> | ||
65 | |||
66 | |||
67 | #include <linux/version.h> | ||
68 | #include <linux/usb/input.h> | ||
69 | |||
70 | /* Version with a Major number of 2 is for kernel inclusion only. */ | ||
71 | #define GTCO_VERSION "2.00.0006" | ||
72 | |||
73 | |||
74 | /* MACROS */ | ||
75 | |||
76 | #define VENDOR_ID_GTCO 0x078C | ||
77 | #define PID_400 0x400 | ||
78 | #define PID_401 0x401 | ||
79 | #define PID_1000 0x1000 | ||
80 | #define PID_1001 0x1001 | ||
81 | #define PID_1002 0x1002 | ||
82 | |||
83 | /* Max size of a single report */ | ||
84 | #define REPORT_MAX_SIZE 10 | ||
85 | |||
86 | |||
87 | /* Bitmask whether pen is in range */ | ||
88 | #define MASK_INRANGE 0x20 | ||
89 | #define MASK_BUTTON 0x01F | ||
90 | |||
91 | #define PATHLENGTH 64 | ||
92 | |||
93 | /* DATA STRUCTURES */ | ||
94 | |||
95 | /* Device table */ | ||
96 | static struct usb_device_id gtco_usbid_table [] = { | ||
97 | { USB_DEVICE(VENDOR_ID_GTCO, PID_400) }, | ||
98 | { USB_DEVICE(VENDOR_ID_GTCO, PID_401) }, | ||
99 | { USB_DEVICE(VENDOR_ID_GTCO, PID_1000) }, | ||
100 | { USB_DEVICE(VENDOR_ID_GTCO, PID_1001) }, | ||
101 | { USB_DEVICE(VENDOR_ID_GTCO, PID_1002) }, | ||
102 | { } | ||
103 | }; | ||
104 | MODULE_DEVICE_TABLE (usb, gtco_usbid_table); | ||
105 | |||
106 | |||
107 | /* Structure to hold all of our device specific stuff */ | ||
108 | struct gtco { | ||
109 | |||
110 | struct input_dev *inputdevice; /* input device struct pointer */ | ||
111 | struct usb_device *usbdev; /* the usb device for this device */ | ||
112 | struct urb *urbinfo; /* urb for incoming reports */ | ||
113 | dma_addr_t buf_dma; /* dma addr of the data buffer*/ | ||
114 | unsigned char * buffer; /* databuffer for reports */ | ||
115 | |||
116 | char usbpath[PATHLENGTH]; | ||
117 | int openCount; | ||
118 | |||
119 | /* Information pulled from Report Descriptor */ | ||
120 | u32 usage; | ||
121 | u32 min_X; | ||
122 | u32 max_X; | ||
123 | u32 min_Y; | ||
124 | u32 max_Y; | ||
125 | s8 mintilt_X; | ||
126 | s8 maxtilt_X; | ||
127 | s8 mintilt_Y; | ||
128 | s8 maxtilt_Y; | ||
129 | u32 maxpressure; | ||
130 | u32 minpressure; | ||
131 | }; | ||
132 | |||
133 | |||
134 | |||
135 | /* Code for parsing the HID REPORT DESCRIPTOR */ | ||
136 | |||
137 | /* From HID1.11 spec */ | ||
138 | struct hid_descriptor | ||
139 | { | ||
140 | struct usb_descriptor_header header; | ||
141 | __le16 bcdHID; | ||
142 | u8 bCountryCode; | ||
143 | u8 bNumDescriptors; | ||
144 | u8 bDescriptorType; | ||
145 | __le16 wDescriptorLength; | ||
146 | } __attribute__ ((packed)); | ||
147 | |||
148 | |||
149 | #define HID_DESCRIPTOR_SIZE 9 | ||
150 | #define HID_DEVICE_TYPE 33 | ||
151 | #define REPORT_DEVICE_TYPE 34 | ||
152 | |||
153 | |||
154 | #define PREF_TAG(x) ((x)>>4) | ||
155 | #define PREF_TYPE(x) ((x>>2)&0x03) | ||
156 | #define PREF_SIZE(x) ((x)&0x03) | ||
157 | |||
158 | #define TYPE_MAIN 0 | ||
159 | #define TYPE_GLOBAL 1 | ||
160 | #define TYPE_LOCAL 2 | ||
161 | #define TYPE_RESERVED 3 | ||
162 | |||
163 | #define TAG_MAIN_INPUT 0x8 | ||
164 | #define TAG_MAIN_OUTPUT 0x9 | ||
165 | #define TAG_MAIN_FEATURE 0xB | ||
166 | #define TAG_MAIN_COL_START 0xA | ||
167 | #define TAG_MAIN_COL_END 0xC | ||
168 | |||
169 | #define TAG_GLOB_USAGE 0 | ||
170 | #define TAG_GLOB_LOG_MIN 1 | ||
171 | #define TAG_GLOB_LOG_MAX 2 | ||
172 | #define TAG_GLOB_PHYS_MIN 3 | ||
173 | #define TAG_GLOB_PHYS_MAX 4 | ||
174 | #define TAG_GLOB_UNIT_EXP 5 | ||
175 | #define TAG_GLOB_UNIT 6 | ||
176 | #define TAG_GLOB_REPORT_SZ 7 | ||
177 | #define TAG_GLOB_REPORT_ID 8 | ||
178 | #define TAG_GLOB_REPORT_CNT 9 | ||
179 | #define TAG_GLOB_PUSH 10 | ||
180 | #define TAG_GLOB_POP 11 | ||
181 | |||
182 | #define TAG_GLOB_MAX 12 | ||
183 | |||
184 | #define DIGITIZER_USAGE_TIP_PRESSURE 0x30 | ||
185 | #define DIGITIZER_USAGE_TILT_X 0x3D | ||
186 | #define DIGITIZER_USAGE_TILT_Y 0x3E | ||
187 | |||
188 | |||
189 | /* | ||
190 | * This is an abbreviated parser for the HID Report Descriptor. We | ||
191 | * know what devices we are talking to, so this is by no means meant | ||
192 | * to be generic. We can make some safe assumptions: | ||
193 | * | ||
194 | * - We know there are no LONG tags, all short | ||
195 | * - We know that we have no MAIN Feature and MAIN Output items | ||
196 | * - We know what the IRQ reports are supposed to look like. | ||
197 | * | ||
198 | * The main purpose of this is to use the HID report desc to figure | ||
199 | * out the mins and maxs of the fields in the IRQ reports. The IRQ | ||
200 | * reports for 400/401 change slightly if the max X is bigger than 64K. | ||
201 | * | ||
202 | */ | ||
203 | static void parse_hid_report_descriptor(struct gtco *device, char * report, | ||
204 | int length) | ||
205 | { | ||
206 | int x, i = 0; | ||
207 | |||
208 | /* Tag primitive vars */ | ||
209 | __u8 prefix; | ||
210 | __u8 size; | ||
211 | __u8 tag; | ||
212 | __u8 type; | ||
213 | __u8 data = 0; | ||
214 | __u16 data16 = 0; | ||
215 | __u32 data32 = 0; | ||
216 | |||
217 | /* For parsing logic */ | ||
218 | int inputnum = 0; | ||
219 | __u32 usage = 0; | ||
220 | |||
221 | /* Global Values, indexed by TAG */ | ||
222 | __u32 globalval[TAG_GLOB_MAX]; | ||
223 | __u32 oldval[TAG_GLOB_MAX]; | ||
224 | |||
225 | /* Debug stuff */ | ||
226 | char maintype = 'x'; | ||
227 | char globtype[12]; | ||
228 | int indent = 0; | ||
229 | char indentstr[10] = ""; | ||
230 | |||
231 | |||
232 | dbg("======>>>>>>PARSE<<<<<<======"); | ||
233 | |||
234 | /* Walk this report and pull out the info we need */ | ||
235 | while (i < length) { | ||
236 | prefix = report[i]; | ||
237 | |||
238 | /* Skip over prefix */ | ||
239 | i++; | ||
240 | |||
241 | /* Determine data size and save the data in the proper variable */ | ||
242 | size = PREF_SIZE(prefix); | ||
243 | switch (size) { | ||
244 | case 1: | ||
245 | data = report[i]; | ||
246 | break; | ||
247 | case 2: | ||
248 | data16 = le16_to_cpu(get_unaligned((__le16 *)&report[i])); | ||
249 | break; | ||
250 | case 3: | ||
251 | size = 4; | ||
252 | data32 = le32_to_cpu(get_unaligned((__le32 *)&report[i])); | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | /* Skip size of data */ | ||
257 | i += size; | ||
258 | |||
259 | /* What we do depends on the tag type */ | ||
260 | tag = PREF_TAG(prefix); | ||
261 | type = PREF_TYPE(prefix); | ||
262 | switch (type) { | ||
263 | case TYPE_MAIN: | ||
264 | strcpy(globtype, ""); | ||
265 | switch (tag) { | ||
266 | |||
267 | case TAG_MAIN_INPUT: | ||
268 | /* | ||
269 | * The INPUT MAIN tag signifies this is | ||
270 | * information from a report. We need to | ||
271 | * figure out what it is and store the | ||
272 | * min/max values | ||
273 | */ | ||
274 | |||
275 | maintype = 'I'; | ||
276 | if (data == 2) | ||
277 | strcpy(globtype, "Variable"); | ||
278 | else if (data == 3) | ||
279 | strcpy(globtype, "Var|Const"); | ||
280 | |||
281 | dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits", | ||
282 | globalval[TAG_GLOB_REPORT_ID], inputnum, | ||
283 | globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX], | ||
284 | globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN], | ||
285 | globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]); | ||
286 | |||
287 | |||
288 | /* | ||
289 | We can assume that the first two input items | ||
290 | are always the X and Y coordinates. After | ||
291 | that, we look for everything else by | ||
292 | local usage value | ||
293 | */ | ||
294 | switch (inputnum) { | ||
295 | case 0: /* X coord */ | ||
296 | dbg("GER: X Usage: 0x%x", usage); | ||
297 | if (device->max_X == 0) { | ||
298 | device->max_X = globalval[TAG_GLOB_LOG_MAX]; | ||
299 | device->min_X = globalval[TAG_GLOB_LOG_MIN]; | ||
300 | } | ||
301 | break; | ||
302 | |||
303 | case 1: /* Y coord */ | ||
304 | dbg("GER: Y Usage: 0x%x", usage); | ||
305 | if (device->max_Y == 0) { | ||
306 | device->max_Y = globalval[TAG_GLOB_LOG_MAX]; | ||
307 | device->min_Y = globalval[TAG_GLOB_LOG_MIN]; | ||
308 | } | ||
309 | break; | ||
310 | |||
311 | default: | ||
312 | /* Tilt X */ | ||
313 | if (usage == DIGITIZER_USAGE_TILT_X) { | ||
314 | if (device->maxtilt_X == 0) { | ||
315 | device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX]; | ||
316 | device->mintilt_X = globalval[TAG_GLOB_LOG_MIN]; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | /* Tilt Y */ | ||
321 | if (usage == DIGITIZER_USAGE_TILT_Y) { | ||
322 | if (device->maxtilt_Y == 0) { | ||
323 | device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX]; | ||
324 | device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN]; | ||
325 | } | ||
326 | } | ||
327 | |||
328 | /* Pressure */ | ||
329 | if (usage == DIGITIZER_USAGE_TIP_PRESSURE) { | ||
330 | if (device->maxpressure == 0) { | ||
331 | device->maxpressure = globalval[TAG_GLOB_LOG_MAX]; | ||
332 | device->minpressure = globalval[TAG_GLOB_LOG_MIN]; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | break; | ||
337 | } | ||
338 | |||
339 | inputnum++; | ||
340 | break; | ||
341 | |||
342 | case TAG_MAIN_OUTPUT: | ||
343 | maintype = 'O'; | ||
344 | break; | ||
345 | |||
346 | case TAG_MAIN_FEATURE: | ||
347 | maintype = 'F'; | ||
348 | break; | ||
349 | |||
350 | case TAG_MAIN_COL_START: | ||
351 | maintype = 'S'; | ||
352 | |||
353 | if (data == 0) { | ||
354 | dbg("======>>>>>> Physical"); | ||
355 | strcpy(globtype, "Physical"); | ||
356 | } else | ||
357 | dbg("======>>>>>>"); | ||
358 | |||
359 | /* Indent the debug output */ | ||
360 | indent++; | ||
361 | for (x = 0; x < indent; x++) | ||
362 | indentstr[x] = '-'; | ||
363 | indentstr[x] = 0; | ||
364 | |||
365 | /* Save global tags */ | ||
366 | for (x = 0; x < TAG_GLOB_MAX; x++) | ||
367 | oldval[x] = globalval[x]; | ||
368 | |||
369 | break; | ||
370 | |||
371 | case TAG_MAIN_COL_END: | ||
372 | dbg("<<<<<<======"); | ||
373 | maintype = 'E'; | ||
374 | indent--; | ||
375 | for (x = 0; x < indent; x++) | ||
376 | indentstr[x] = '-'; | ||
377 | indentstr[x] = 0; | ||
378 | |||
379 | /* Copy global tags back */ | ||
380 | for (x = 0; x < TAG_GLOB_MAX; x++) | ||
381 | globalval[x] = oldval[x]; | ||
382 | |||
383 | break; | ||
384 | } | ||
385 | |||
386 | switch (size) { | ||
387 | case 1: | ||
388 | dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", | ||
389 | indentstr, tag, maintype, size, globtype, data); | ||
390 | break; | ||
391 | |||
392 | case 2: | ||
393 | dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", | ||
394 | indentstr, tag, maintype, size, globtype, data16); | ||
395 | break; | ||
396 | |||
397 | case 4: | ||
398 | dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", | ||
399 | indentstr, tag, maintype, size, globtype, data32); | ||
400 | break; | ||
401 | } | ||
402 | break; | ||
403 | |||
404 | case TYPE_GLOBAL: | ||
405 | switch (tag) { | ||
406 | case TAG_GLOB_USAGE: | ||
407 | /* | ||
408 | * First time we hit the global usage tag, | ||
409 | * it should tell us the type of device | ||
410 | */ | ||
411 | if (device->usage == 0) | ||
412 | device->usage = data; | ||
413 | |||
414 | strcpy(globtype, "USAGE"); | ||
415 | break; | ||
416 | |||
417 | case TAG_GLOB_LOG_MIN: | ||
418 | strcpy(globtype, "LOG_MIN"); | ||
419 | break; | ||
420 | |||
421 | case TAG_GLOB_LOG_MAX: | ||
422 | strcpy(globtype, "LOG_MAX"); | ||
423 | break; | ||
424 | |||
425 | case TAG_GLOB_PHYS_MIN: | ||
426 | strcpy(globtype, "PHYS_MIN"); | ||
427 | break; | ||
428 | |||
429 | case TAG_GLOB_PHYS_MAX: | ||
430 | strcpy(globtype, "PHYS_MAX"); | ||
431 | break; | ||
432 | |||
433 | case TAG_GLOB_UNIT_EXP: | ||
434 | strcpy(globtype, "EXP"); | ||
435 | break; | ||
436 | |||
437 | case TAG_GLOB_UNIT: | ||
438 | strcpy(globtype, "UNIT"); | ||
439 | break; | ||
440 | |||
441 | case TAG_GLOB_REPORT_SZ: | ||
442 | strcpy(globtype, "REPORT_SZ"); | ||
443 | break; | ||
444 | |||
445 | case TAG_GLOB_REPORT_ID: | ||
446 | strcpy(globtype, "REPORT_ID"); | ||
447 | /* New report, restart numbering */ | ||
448 | inputnum = 0; | ||
449 | break; | ||
450 | |||
451 | case TAG_GLOB_REPORT_CNT: | ||
452 | strcpy(globtype, "REPORT_CNT"); | ||
453 | break; | ||
454 | |||
455 | case TAG_GLOB_PUSH: | ||
456 | strcpy(globtype, "PUSH"); | ||
457 | break; | ||
458 | |||
459 | case TAG_GLOB_POP: | ||
460 | strcpy(globtype, "POP"); | ||
461 | break; | ||
462 | } | ||
463 | |||
464 | /* Check to make sure we have a good tag number | ||
465 | so we don't overflow array */ | ||
466 | if (tag < TAG_GLOB_MAX) { | ||
467 | switch (size) { | ||
468 | case 1: | ||
469 | dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", | ||
470 | indentstr, globtype, tag, size, data); | ||
471 | globalval[tag] = data; | ||
472 | break; | ||
473 | |||
474 | case 2: | ||
475 | dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", | ||
476 | indentstr, globtype, tag, size, data16); | ||
477 | globalval[tag] = data16; | ||
478 | break; | ||
479 | |||
480 | case 4: | ||
481 | dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", | ||
482 | indentstr, globtype, tag, size, data32); | ||
483 | globalval[tag] = data32; | ||
484 | break; | ||
485 | } | ||
486 | } else { | ||
487 | dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ", | ||
488 | indentstr, tag, size); | ||
489 | } | ||
490 | break; | ||
491 | |||
492 | case TYPE_LOCAL: | ||
493 | switch (tag) { | ||
494 | case TAG_GLOB_USAGE: | ||
495 | strcpy(globtype, "USAGE"); | ||
496 | /* Always 1 byte */ | ||
497 | usage = data; | ||
498 | break; | ||
499 | |||
500 | case TAG_GLOB_LOG_MIN: | ||
501 | strcpy(globtype, "MIN"); | ||
502 | break; | ||
503 | |||
504 | case TAG_GLOB_LOG_MAX: | ||
505 | strcpy(globtype, "MAX"); | ||
506 | break; | ||
507 | |||
508 | default: | ||
509 | strcpy(globtype, "UNKNOWN"); | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | switch (size) { | ||
514 | case 1: | ||
515 | dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", | ||
516 | indentstr, tag, globtype, size, data); | ||
517 | break; | ||
518 | |||
519 | case 2: | ||
520 | dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", | ||
521 | indentstr, tag, globtype, size, data16); | ||
522 | break; | ||
523 | |||
524 | case 4: | ||
525 | dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", | ||
526 | indentstr, tag, globtype, size, data32); | ||
527 | break; | ||
528 | } | ||
529 | |||
530 | break; | ||
531 | } | ||
532 | } | ||
533 | } | ||
534 | |||
535 | /* INPUT DRIVER Routines */ | ||
536 | |||
537 | /* | ||
538 | * Called when opening the input device. This will submit the URB to | ||
539 | * the usb system so we start getting reports | ||
540 | */ | ||
541 | static int gtco_input_open(struct input_dev *inputdev) | ||
542 | { | ||
543 | struct gtco *device = input_get_drvdata(inputdev); | ||
544 | |||
545 | device->urbinfo->dev = device->usbdev; | ||
546 | if (usb_submit_urb(device->urbinfo, GFP_KERNEL)) | ||
547 | return -EIO; | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | /* | ||
553 | * Called when closing the input device. This will unlink the URB | ||
554 | */ | ||
555 | static void gtco_input_close(struct input_dev *inputdev) | ||
556 | { | ||
557 | struct gtco *device = input_get_drvdata(inputdev); | ||
558 | |||
559 | usb_kill_urb(device->urbinfo); | ||
560 | } | ||
561 | |||
562 | |||
563 | /* | ||
564 | * Setup input device capabilities. Tell the input system what this | ||
565 | * device is capable of generating. | ||
566 | * | ||
567 | * This information is based on what is read from the HID report and | ||
568 | * placed in the struct gtco structure | ||
569 | * | ||
570 | */ | ||
571 | static void gtco_setup_caps(struct input_dev *inputdev) | ||
572 | { | ||
573 | struct gtco *device = input_get_drvdata(inputdev); | ||
574 | |||
575 | /* Which events */ | ||
576 | inputdev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); | ||
577 | |||
578 | /* Misc event menu block */ | ||
579 | inputdev->mscbit[0] = BIT(MSC_SCAN)|BIT(MSC_SERIAL)|BIT(MSC_RAW) ; | ||
580 | |||
581 | /* Absolute values based on HID report info */ | ||
582 | input_set_abs_params(inputdev, ABS_X, device->min_X, device->max_X, | ||
583 | 0, 0); | ||
584 | input_set_abs_params(inputdev, ABS_Y, device->min_Y, device->max_Y, | ||
585 | 0, 0); | ||
586 | |||
587 | /* Proximity */ | ||
588 | input_set_abs_params(inputdev, ABS_DISTANCE, 0, 1, 0, 0); | ||
589 | |||
590 | /* Tilt & pressure */ | ||
591 | input_set_abs_params(inputdev, ABS_TILT_X, device->mintilt_X, | ||
592 | device->maxtilt_X, 0, 0); | ||
593 | input_set_abs_params(inputdev, ABS_TILT_Y, device->mintilt_Y, | ||
594 | device->maxtilt_Y, 0, 0); | ||
595 | input_set_abs_params(inputdev, ABS_PRESSURE, device->minpressure, | ||
596 | device->maxpressure, 0, 0); | ||
597 | |||
598 | /* Transducer */ | ||
599 | input_set_abs_params(inputdev, ABS_MISC, 0, 0xFF, 0, 0); | ||
600 | } | ||
601 | |||
602 | /* USB Routines */ | ||
603 | |||
604 | /* | ||
605 | * URB callback routine. Called when we get IRQ reports from the | ||
606 | * digitizer. | ||
607 | * | ||
608 | * This bridges the USB and input device worlds. It generates events | ||
609 | * on the input device based on the USB reports. | ||
610 | */ | ||
611 | static void gtco_urb_callback(struct urb *urbinfo) | ||
612 | { | ||
613 | struct gtco *device = urbinfo->context; | ||
614 | struct input_dev *inputdev; | ||
615 | int rc; | ||
616 | u32 val = 0; | ||
617 | s8 valsigned = 0; | ||
618 | char le_buffer[2]; | ||
619 | |||
620 | inputdev = device->inputdevice; | ||
621 | |||
622 | /* Was callback OK? */ | ||
623 | if (urbinfo->status == -ECONNRESET || | ||
624 | urbinfo->status == -ENOENT || | ||
625 | urbinfo->status == -ESHUTDOWN) { | ||
626 | |||
627 | /* Shutdown is occurring. Return and don't queue up any more */ | ||
628 | return; | ||
629 | } | ||
630 | |||
631 | if (urbinfo->status != 0) { | ||
632 | /* | ||
633 | * Some unknown error. Hopefully temporary. Just go and | ||
634 | * requeue an URB | ||
635 | */ | ||
636 | goto resubmit; | ||
637 | } | ||
638 | |||
639 | /* | ||
640 | * Good URB, now process | ||
641 | */ | ||
642 | |||
643 | /* PID dependent when we interpret the report */ | ||
644 | if (inputdev->id.product == PID_1000 || | ||
645 | inputdev->id.product == PID_1001 || | ||
646 | inputdev->id.product == PID_1002) { | ||
647 | |||
648 | /* | ||
649 | * Switch on the report ID | ||
650 | * Conveniently, the reports have more information, the higher | ||
651 | * the report number. We can just fall through the case | ||
652 | * statements if we start with the highest number report | ||
653 | */ | ||
654 | switch (device->buffer[0]) { | ||
655 | case 5: | ||
656 | /* Pressure is 9 bits */ | ||
657 | val = ((u16)(device->buffer[8]) << 1); | ||
658 | val |= (u16)(device->buffer[7] >> 7); | ||
659 | input_report_abs(inputdev, ABS_PRESSURE, | ||
660 | device->buffer[8]); | ||
661 | |||
662 | /* Mask out the Y tilt value used for pressure */ | ||
663 | device->buffer[7] = (u8)((device->buffer[7]) & 0x7F); | ||
664 | |||
665 | /* Fall thru */ | ||
666 | case 4: | ||
667 | /* Tilt */ | ||
668 | |||
669 | /* Sign extend these 7 bit numbers. */ | ||
670 | if (device->buffer[6] & 0x40) | ||
671 | device->buffer[6] |= 0x80; | ||
672 | |||
673 | if (device->buffer[7] & 0x40) | ||
674 | device->buffer[7] |= 0x80; | ||
675 | |||
676 | |||
677 | valsigned = (device->buffer[6]); | ||
678 | input_report_abs(inputdev, ABS_TILT_X, (s32)valsigned); | ||
679 | |||
680 | valsigned = (device->buffer[7]); | ||
681 | input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned); | ||
682 | |||
683 | /* Fall thru */ | ||
684 | case 2: | ||
685 | case 3: | ||
686 | /* Convert buttons, only 5 bits possible */ | ||
687 | val = (device->buffer[5]) & MASK_BUTTON; | ||
688 | |||
689 | /* We don't apply any meaning to the bitmask, | ||
690 | just report */ | ||
691 | input_event(inputdev, EV_MSC, MSC_SERIAL, val); | ||
692 | |||
693 | /* Fall thru */ | ||
694 | case 1: | ||
695 | /* All reports have X and Y coords in the same place */ | ||
696 | val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1])); | ||
697 | input_report_abs(inputdev, ABS_X, val); | ||
698 | |||
699 | val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3])); | ||
700 | input_report_abs(inputdev, ABS_Y, val); | ||
701 | |||
702 | /* Ditto for proximity bit */ | ||
703 | val = device->buffer[5] & MASK_INRANGE ? 1 : 0; | ||
704 | input_report_abs(inputdev, ABS_DISTANCE, val); | ||
705 | |||
706 | /* Report 1 is an exception to how we handle buttons */ | ||
707 | /* Buttons are an index, not a bitmask */ | ||
708 | if (device->buffer[0] == 1) { | ||
709 | |||
710 | /* | ||
711 | * Convert buttons, 5 bit index | ||
712 | * Report value of index set as one, | ||
713 | * the rest as 0 | ||
714 | */ | ||
715 | val = device->buffer[5] & MASK_BUTTON; | ||
716 | dbg("======>>>>>>REPORT 1: val 0x%X(%d)", | ||
717 | val, val); | ||
718 | |||
719 | /* | ||
720 | * We don't apply any meaning to the button | ||
721 | * index, just report it | ||
722 | */ | ||
723 | input_event(inputdev, EV_MSC, MSC_SERIAL, val); | ||
724 | } | ||
725 | break; | ||
726 | |||
727 | case 7: | ||
728 | /* Menu blocks */ | ||
729 | input_event(inputdev, EV_MSC, MSC_SCAN, | ||
730 | device->buffer[1]); | ||
731 | break; | ||
732 | } | ||
733 | } | ||
734 | |||
735 | /* Other pid class */ | ||
736 | if (inputdev->id.product == PID_400 || | ||
737 | inputdev->id.product == PID_401) { | ||
738 | |||
739 | /* Report 2 */ | ||
740 | if (device->buffer[0] == 2) { | ||
741 | /* Menu blocks */ | ||
742 | input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]); | ||
743 | } | ||
744 | |||
745 | /* Report 1 */ | ||
746 | if (device->buffer[0] == 1) { | ||
747 | char buttonbyte; | ||
748 | |||
749 | /* IF X max > 64K, we still a bit from the y report */ | ||
750 | if (device->max_X > 0x10000) { | ||
751 | |||
752 | val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]); | ||
753 | val |= (u32)(((u8)device->buffer[3] & 0x1) << 16); | ||
754 | |||
755 | input_report_abs(inputdev, ABS_X, val); | ||
756 | |||
757 | le_buffer[0] = (u8)((u8)(device->buffer[3]) >> 1); | ||
758 | le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7); | ||
759 | |||
760 | le_buffer[1] = (u8)(device->buffer[4] >> 1); | ||
761 | le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7); | ||
762 | |||
763 | val = le16_to_cpu(get_unaligned((__le16 *)le_buffer)); | ||
764 | input_report_abs(inputdev, ABS_Y, val); | ||
765 | |||
766 | /* | ||
767 | * Shift the button byte right by one to | ||
768 | * make it look like the standard report | ||
769 | */ | ||
770 | buttonbyte = device->buffer[5] >> 1; | ||
771 | } else { | ||
772 | |||
773 | val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1])); | ||
774 | input_report_abs(inputdev, ABS_X, val); | ||
775 | |||
776 | val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3])); | ||
777 | input_report_abs(inputdev, ABS_Y, val); | ||
778 | |||
779 | buttonbyte = device->buffer[5]; | ||
780 | } | ||
781 | |||
782 | /* BUTTONS and PROXIMITY */ | ||
783 | val = buttonbyte & MASK_INRANGE ? 1 : 0; | ||
784 | input_report_abs(inputdev, ABS_DISTANCE, val); | ||
785 | |||
786 | /* Convert buttons, only 4 bits possible */ | ||
787 | val = buttonbyte & 0x0F; | ||
788 | #ifdef USE_BUTTONS | ||
789 | for (i = 0; i < 5; i++) | ||
790 | input_report_key(inputdev, BTN_DIGI + i, val & (1 << i)); | ||
791 | #else | ||
792 | /* We don't apply any meaning to the bitmask, just report */ | ||
793 | input_event(inputdev, EV_MSC, MSC_SERIAL, val); | ||
794 | #endif | ||
795 | |||
796 | /* TRANSDUCER */ | ||
797 | input_report_abs(inputdev, ABS_MISC, device->buffer[6]); | ||
798 | } | ||
799 | } | ||
800 | |||
801 | /* Everybody gets report ID's */ | ||
802 | input_event(inputdev, EV_MSC, MSC_RAW, device->buffer[0]); | ||
803 | |||
804 | /* Sync it up */ | ||
805 | input_sync(inputdev); | ||
806 | |||
807 | resubmit: | ||
808 | rc = usb_submit_urb(urbinfo, GFP_ATOMIC); | ||
809 | if (rc != 0) | ||
810 | err("usb_submit_urb failed rc=0x%x", rc); | ||
811 | } | ||
812 | |||
813 | /* | ||
814 | * The probe routine. This is called when the kernel find the matching USB | ||
815 | * vendor/product. We do the following: | ||
816 | * | ||
817 | * - Allocate mem for a local structure to manage the device | ||
818 | * - Request a HID Report Descriptor from the device and parse it to | ||
819 | * find out the device parameters | ||
820 | * - Create an input device and assign it attributes | ||
821 | * - Allocate an URB so the device can talk to us when the input | ||
822 | * queue is open | ||
823 | */ | ||
824 | static int gtco_probe(struct usb_interface *usbinterface, | ||
825 | const struct usb_device_id *id) | ||
826 | { | ||
827 | |||
828 | struct gtco *gtco; | ||
829 | struct input_dev *input_dev; | ||
830 | struct hid_descriptor *hid_desc; | ||
831 | char *report = NULL; | ||
832 | int result = 0, retry; | ||
833 | int error; | ||
834 | struct usb_endpoint_descriptor *endpoint; | ||
835 | |||
836 | /* Allocate memory for device structure */ | ||
837 | gtco = kzalloc(sizeof(struct gtco), GFP_KERNEL); | ||
838 | input_dev = input_allocate_device(); | ||
839 | if (!gtco || !input_dev) { | ||
840 | err("No more memory"); | ||
841 | error = -ENOMEM; | ||
842 | goto err_free_devs; | ||
843 | } | ||
844 | |||
845 | /* Set pointer to the input device */ | ||
846 | gtco->inputdevice = input_dev; | ||
847 | |||
848 | /* Save interface information */ | ||
849 | gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); | ||
850 | |||
851 | /* Allocate some data for incoming reports */ | ||
852 | gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE, | ||
853 | GFP_KERNEL, >co->buf_dma); | ||
854 | if (!gtco->buffer) { | ||
855 | err("No more memory for us buffers"); | ||
856 | error = -ENOMEM; | ||
857 | goto err_free_devs; | ||
858 | } | ||
859 | |||
860 | /* Allocate URB for reports */ | ||
861 | gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL); | ||
862 | if (!gtco->urbinfo) { | ||
863 | err("Failed to allocate URB"); | ||
864 | return -ENOMEM; | ||
865 | goto err_free_buf; | ||
866 | } | ||
867 | |||
868 | /* | ||
869 | * The endpoint is always altsetting 0, we know this since we know | ||
870 | * this device only has one interrupt endpoint | ||
871 | */ | ||
872 | endpoint = &usbinterface->altsetting[0].endpoint[0].desc; | ||
873 | |||
874 | /* Some debug */ | ||
875 | dbg("gtco # interfaces: %d", usbinterface->num_altsetting); | ||
876 | dbg("num endpoints: %d", usbinterface->cur_altsetting->desc.bNumEndpoints); | ||
877 | dbg("interface class: %d", usbinterface->cur_altsetting->desc.bInterfaceClass); | ||
878 | dbg("endpoint: attribute:0x%x type:0x%x", endpoint->bmAttributes, endpoint->bDescriptorType); | ||
879 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) | ||
880 | dbg("endpoint: we have interrupt endpoint\n"); | ||
881 | |||
882 | dbg("endpoint extra len:%d ", usbinterface->altsetting[0].extralen); | ||
883 | |||
884 | /* | ||
885 | * Find the HID descriptor so we can find out the size of the | ||
886 | * HID report descriptor | ||
887 | */ | ||
888 | if (usb_get_extra_descriptor(usbinterface->cur_altsetting, | ||
889 | HID_DEVICE_TYPE, &hid_desc) != 0){ | ||
890 | err("Can't retrieve exta USB descriptor to get hid report descriptor length"); | ||
891 | error = -EIO; | ||
892 | goto err_free_urb; | ||
893 | } | ||
894 | |||
895 | dbg("Extra descriptor success: type:%d len:%d", | ||
896 | hid_desc->bDescriptorType, hid_desc->wDescriptorLength); | ||
897 | |||
898 | report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL); | ||
899 | if (!report) { | ||
900 | err("No more memory for report"); | ||
901 | error = -ENOMEM; | ||
902 | goto err_free_urb; | ||
903 | } | ||
904 | |||
905 | /* Couple of tries to get reply */ | ||
906 | for (retry = 0; retry < 3; retry++) { | ||
907 | result = usb_control_msg(gtco->usbdev, | ||
908 | usb_rcvctrlpipe(gtco->usbdev, 0), | ||
909 | USB_REQ_GET_DESCRIPTOR, | ||
910 | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
911 | REPORT_DEVICE_TYPE << 8, | ||
912 | 0, /* interface */ | ||
913 | report, | ||
914 | hid_desc->wDescriptorLength, | ||
915 | 5000); /* 5 secs */ | ||
916 | |||
917 | if (result == hid_desc->wDescriptorLength) | ||
918 | break; | ||
919 | } | ||
920 | |||
921 | /* If we didn't get the report, fail */ | ||
922 | dbg("usb_control_msg result: :%d", result); | ||
923 | if (result != hid_desc->wDescriptorLength) { | ||
924 | err("Failed to get HID Report Descriptor of size: %d", | ||
925 | hid_desc->wDescriptorLength); | ||
926 | error = -EIO; | ||
927 | goto err_free_urb; | ||
928 | } | ||
929 | |||
930 | /* Now we parse the report */ | ||
931 | parse_hid_report_descriptor(gtco, report, result); | ||
932 | |||
933 | /* Now we delete it */ | ||
934 | kfree(report); | ||
935 | |||
936 | /* Create a device file node */ | ||
937 | usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath)); | ||
938 | strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath)); | ||
939 | |||
940 | /* Set Input device functions */ | ||
941 | input_dev->open = gtco_input_open; | ||
942 | input_dev->close = gtco_input_close; | ||
943 | |||
944 | /* Set input device information */ | ||
945 | input_dev->name = "GTCO_CalComp"; | ||
946 | input_dev->phys = gtco->usbpath; | ||
947 | |||
948 | input_set_drvdata(input_dev, gtco); | ||
949 | |||
950 | /* Now set up all the input device capabilities */ | ||
951 | gtco_setup_caps(input_dev); | ||
952 | |||
953 | /* Set input device required ID information */ | ||
954 | usb_to_input_id(gtco->usbdev, &input_dev->id); | ||
955 | input_dev->dev.parent = &usbinterface->dev; | ||
956 | |||
957 | /* Setup the URB, it will be posted later on open of input device */ | ||
958 | endpoint = &usbinterface->altsetting[0].endpoint[0].desc; | ||
959 | |||
960 | usb_fill_int_urb(gtco->urbinfo, | ||
961 | gtco->usbdev, | ||
962 | usb_rcvintpipe(gtco->usbdev, | ||
963 | endpoint->bEndpointAddress), | ||
964 | gtco->buffer, | ||
965 | REPORT_MAX_SIZE, | ||
966 | gtco_urb_callback, | ||
967 | gtco, | ||
968 | endpoint->bInterval); | ||
969 | |||
970 | gtco->urbinfo->transfer_dma = gtco->buf_dma; | ||
971 | gtco->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
972 | |||
973 | /* Save gtco pointer in USB interface gtco */ | ||
974 | usb_set_intfdata(usbinterface, gtco); | ||
975 | |||
976 | /* All done, now register the input device */ | ||
977 | error = input_register_device(input_dev); | ||
978 | if (error) | ||
979 | goto err_free_urb; | ||
980 | |||
981 | return 0; | ||
982 | |||
983 | err_free_urb: | ||
984 | usb_free_urb(gtco->urbinfo); | ||
985 | err_free_buf: | ||
986 | usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, | ||
987 | gtco->buffer, gtco->buf_dma); | ||
988 | err_free_devs: | ||
989 | kfree(report); | ||
990 | input_free_device(input_dev); | ||
991 | kfree(gtco); | ||
992 | return error; | ||
993 | } | ||
994 | |||
995 | /* | ||
996 | * This function is a standard USB function called when the USB device | ||
997 | * is disconnected. We will get rid of the URV, de-register the input | ||
998 | * device, and free up allocated memory | ||
999 | */ | ||
1000 | static void gtco_disconnect(struct usb_interface *interface) | ||
1001 | { | ||
1002 | /* Grab private device ptr */ | ||
1003 | struct gtco *gtco = usb_get_intfdata(interface); | ||
1004 | |||
1005 | /* Now reverse all the registration stuff */ | ||
1006 | if (gtco) { | ||
1007 | input_unregister_device(gtco->inputdevice); | ||
1008 | usb_kill_urb(gtco->urbinfo); | ||
1009 | usb_free_urb(gtco->urbinfo); | ||
1010 | usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, | ||
1011 | gtco->buffer, gtco->buf_dma); | ||
1012 | kfree(gtco); | ||
1013 | } | ||
1014 | |||
1015 | info("gtco driver disconnected"); | ||
1016 | } | ||
1017 | |||
1018 | /* STANDARD MODULE LOAD ROUTINES */ | ||
1019 | |||
1020 | static struct usb_driver gtco_driverinfo_table = { | ||
1021 | .name = "gtco", | ||
1022 | .id_table = gtco_usbid_table, | ||
1023 | .probe = gtco_probe, | ||
1024 | .disconnect = gtco_disconnect, | ||
1025 | }; | ||
1026 | |||
1027 | /* | ||
1028 | * Register this module with the USB subsystem | ||
1029 | */ | ||
1030 | static int __init gtco_init(void) | ||
1031 | { | ||
1032 | int error; | ||
1033 | |||
1034 | error = usb_register(>co_driverinfo_table); | ||
1035 | if (error) { | ||
1036 | err("usb_register() failed rc=0x%x", error); | ||
1037 | return error; | ||
1038 | } | ||
1039 | |||
1040 | printk("GTCO usb driver version: %s", GTCO_VERSION); | ||
1041 | return 0; | ||
1042 | } | ||
1043 | |||
1044 | /* | ||
1045 | * Deregister this module with the USB subsystem | ||
1046 | */ | ||
1047 | static void __exit gtco_exit(void) | ||
1048 | { | ||
1049 | usb_deregister(>co_driverinfo_table); | ||
1050 | } | ||
1051 | |||
1052 | module_init(gtco_init); | ||
1053 | module_exit(gtco_exit); | ||
1054 | |||
1055 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c new file mode 100644 index 000000000000..91e6d00d4a43 --- /dev/null +++ b/drivers/input/tablet/kbtab.c | |||
@@ -0,0 +1,226 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/slab.h> | ||
3 | #include <linux/module.h> | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/usb/input.h> | ||
6 | #include <asm/unaligned.h> | ||
7 | |||
8 | /* | ||
9 | * Version Information | ||
10 | * v0.0.1 - Original, extremely basic version, 2.4.xx only | ||
11 | * v0.0.2 - Updated, works with 2.5.62 and 2.4.20; | ||
12 | * - added pressure-threshold modules param code from | ||
13 | * Alex Perry <alex.perry@ieee.org> | ||
14 | */ | ||
15 | |||
16 | #define DRIVER_VERSION "v0.0.2" | ||
17 | #define DRIVER_AUTHOR "Josh Myer <josh@joshisanerd.com>" | ||
18 | #define DRIVER_DESC "USB KB Gear JamStudio Tablet driver" | ||
19 | #define DRIVER_LICENSE "GPL" | ||
20 | |||
21 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
22 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
23 | MODULE_LICENSE(DRIVER_LICENSE); | ||
24 | |||
25 | #define USB_VENDOR_ID_KBGEAR 0x084e | ||
26 | |||
27 | static int kb_pressure_click = 0x10; | ||
28 | module_param(kb_pressure_click, int, 0); | ||
29 | MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks"); | ||
30 | |||
31 | struct kbtab { | ||
32 | unsigned char *data; | ||
33 | dma_addr_t data_dma; | ||
34 | struct input_dev *dev; | ||
35 | struct usb_device *usbdev; | ||
36 | struct urb *irq; | ||
37 | int x, y; | ||
38 | int button; | ||
39 | int pressure; | ||
40 | __u32 serial[2]; | ||
41 | char phys[32]; | ||
42 | }; | ||
43 | |||
44 | static void kbtab_irq(struct urb *urb) | ||
45 | { | ||
46 | struct kbtab *kbtab = urb->context; | ||
47 | unsigned char *data = kbtab->data; | ||
48 | struct input_dev *dev = kbtab->dev; | ||
49 | int retval; | ||
50 | |||
51 | switch (urb->status) { | ||
52 | case 0: | ||
53 | /* success */ | ||
54 | break; | ||
55 | case -ECONNRESET: | ||
56 | case -ENOENT: | ||
57 | case -ESHUTDOWN: | ||
58 | /* this urb is terminated, clean up */ | ||
59 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
60 | return; | ||
61 | default: | ||
62 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
63 | goto exit; | ||
64 | } | ||
65 | |||
66 | kbtab->x = le16_to_cpu(get_unaligned((__le16 *) &data[1])); | ||
67 | kbtab->y = le16_to_cpu(get_unaligned((__le16 *) &data[3])); | ||
68 | |||
69 | kbtab->pressure = (data[5]); | ||
70 | |||
71 | input_report_key(dev, BTN_TOOL_PEN, 1); | ||
72 | |||
73 | input_report_abs(dev, ABS_X, kbtab->x); | ||
74 | input_report_abs(dev, ABS_Y, kbtab->y); | ||
75 | |||
76 | /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ | ||
77 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); | ||
78 | |||
79 | if (-1 == kb_pressure_click) { | ||
80 | input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); | ||
81 | } else { | ||
82 | input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); | ||
83 | }; | ||
84 | |||
85 | input_sync(dev); | ||
86 | |||
87 | exit: | ||
88 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
89 | if (retval) | ||
90 | err ("%s - usb_submit_urb failed with result %d", | ||
91 | __FUNCTION__, retval); | ||
92 | } | ||
93 | |||
94 | static struct usb_device_id kbtab_ids[] = { | ||
95 | { USB_DEVICE(USB_VENDOR_ID_KBGEAR, 0x1001), .driver_info = 0 }, | ||
96 | { } | ||
97 | }; | ||
98 | |||
99 | MODULE_DEVICE_TABLE(usb, kbtab_ids); | ||
100 | |||
101 | static int kbtab_open(struct input_dev *dev) | ||
102 | { | ||
103 | struct kbtab *kbtab = input_get_drvdata(dev); | ||
104 | |||
105 | kbtab->irq->dev = kbtab->usbdev; | ||
106 | if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) | ||
107 | return -EIO; | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static void kbtab_close(struct input_dev *dev) | ||
113 | { | ||
114 | struct kbtab *kbtab = input_get_drvdata(dev); | ||
115 | |||
116 | usb_kill_urb(kbtab->irq); | ||
117 | } | ||
118 | |||
119 | static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
120 | { | ||
121 | struct usb_device *dev = interface_to_usbdev(intf); | ||
122 | struct usb_endpoint_descriptor *endpoint; | ||
123 | struct kbtab *kbtab; | ||
124 | struct input_dev *input_dev; | ||
125 | int error = -ENOMEM; | ||
126 | |||
127 | kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL); | ||
128 | input_dev = input_allocate_device(); | ||
129 | if (!kbtab || !input_dev) | ||
130 | goto fail1; | ||
131 | |||
132 | kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma); | ||
133 | if (!kbtab->data) | ||
134 | goto fail1; | ||
135 | |||
136 | kbtab->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
137 | if (!kbtab->irq) | ||
138 | goto fail2; | ||
139 | |||
140 | kbtab->usbdev = dev; | ||
141 | kbtab->dev = input_dev; | ||
142 | |||
143 | usb_make_path(dev, kbtab->phys, sizeof(kbtab->phys)); | ||
144 | strlcat(kbtab->phys, "/input0", sizeof(kbtab->phys)); | ||
145 | |||
146 | input_dev->name = "KB Gear Tablet"; | ||
147 | input_dev->phys = kbtab->phys; | ||
148 | usb_to_input_id(dev, &input_dev->id); | ||
149 | input_dev->dev.parent = &intf->dev; | ||
150 | |||
151 | input_set_drvdata(input_dev, kbtab); | ||
152 | |||
153 | input_dev->open = kbtab_open; | ||
154 | input_dev->close = kbtab_close; | ||
155 | |||
156 | input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); | ||
157 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
158 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH); | ||
159 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | ||
160 | input_set_abs_params(input_dev, ABS_X, 0, 0x2000, 4, 0); | ||
161 | input_set_abs_params(input_dev, ABS_Y, 0, 0x1750, 4, 0); | ||
162 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0); | ||
163 | |||
164 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | ||
165 | |||
166 | usb_fill_int_urb(kbtab->irq, dev, | ||
167 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | ||
168 | kbtab->data, 8, | ||
169 | kbtab_irq, kbtab, endpoint->bInterval); | ||
170 | kbtab->irq->transfer_dma = kbtab->data_dma; | ||
171 | kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
172 | |||
173 | error = input_register_device(kbtab->dev); | ||
174 | if (error) | ||
175 | goto fail3; | ||
176 | |||
177 | usb_set_intfdata(intf, kbtab); | ||
178 | |||
179 | return 0; | ||
180 | |||
181 | fail3: usb_free_urb(kbtab->irq); | ||
182 | fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); | ||
183 | fail1: input_free_device(input_dev); | ||
184 | kfree(kbtab); | ||
185 | return error; | ||
186 | } | ||
187 | |||
188 | static void kbtab_disconnect(struct usb_interface *intf) | ||
189 | { | ||
190 | struct kbtab *kbtab = usb_get_intfdata(intf); | ||
191 | |||
192 | usb_set_intfdata(intf, NULL); | ||
193 | if (kbtab) { | ||
194 | usb_kill_urb(kbtab->irq); | ||
195 | input_unregister_device(kbtab->dev); | ||
196 | usb_free_urb(kbtab->irq); | ||
197 | usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); | ||
198 | kfree(kbtab); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | static struct usb_driver kbtab_driver = { | ||
203 | .name = "kbtab", | ||
204 | .probe = kbtab_probe, | ||
205 | .disconnect = kbtab_disconnect, | ||
206 | .id_table = kbtab_ids, | ||
207 | }; | ||
208 | |||
209 | static int __init kbtab_init(void) | ||
210 | { | ||
211 | int retval; | ||
212 | retval = usb_register(&kbtab_driver); | ||
213 | if (retval) | ||
214 | goto out; | ||
215 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
216 | out: | ||
217 | return retval; | ||
218 | } | ||
219 | |||
220 | static void __exit kbtab_exit(void) | ||
221 | { | ||
222 | usb_deregister(&kbtab_driver); | ||
223 | } | ||
224 | |||
225 | module_init(kbtab_init); | ||
226 | module_exit(kbtab_exit); | ||
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h new file mode 100644 index 000000000000..ef01a807ec0f --- /dev/null +++ b/drivers/input/tablet/wacom.h | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * drivers/input/tablet/wacom.h | ||
3 | * | ||
4 | * USB Wacom Graphire and Wacom Intuos tablet support | ||
5 | * | ||
6 | * Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz> | ||
7 | * Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk> | ||
8 | * Copyright (c) 2000 Clifford Wolf <clifford@clifford.at> | ||
9 | * Copyright (c) 2000 Sam Mosel <sam.mosel@computer.org> | ||
10 | * Copyright (c) 2000 James E. Blair <corvus@gnu.org> | ||
11 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> | ||
12 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> | ||
13 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> | ||
14 | * Copyright (c) 2002-2006 Ping Cheng <pingc@wacom.com> | ||
15 | * | ||
16 | * ChangeLog: | ||
17 | * v0.1 (vp) - Initial release | ||
18 | * v0.2 (aba) - Support for all buttons / combinations | ||
19 | * v0.3 (vp) - Support for Intuos added | ||
20 | * v0.4 (sm) - Support for more Intuos models, menustrip | ||
21 | * relative mode, proximity. | ||
22 | * v0.5 (vp) - Big cleanup, nifty features removed, | ||
23 | * they belong in userspace | ||
24 | * v1.8 (vp) - Submit URB only when operating, moved to CVS, | ||
25 | * use input_report_key instead of report_btn and | ||
26 | * other cleanups | ||
27 | * v1.11 (vp) - Add URB ->dev setting for new kernels | ||
28 | * v1.11 (jb) - Add support for the 4D Mouse & Lens | ||
29 | * v1.12 (de) - Add support for two more inking pen IDs | ||
30 | * v1.14 (vp) - Use new USB device id probing scheme. | ||
31 | * Fix Wacom Graphire mouse wheel | ||
32 | * v1.18 (vp) - Fix mouse wheel direction | ||
33 | * Make mouse relative | ||
34 | * v1.20 (fl) - Report tool id for Intuos devices | ||
35 | * - Multi tools support | ||
36 | * - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...) | ||
37 | * - Add PL models support | ||
38 | * - Fix Wacom Graphire mouse wheel again | ||
39 | * v1.21 (vp) - Removed protocol descriptions | ||
40 | * - Added MISC_SERIAL for tool serial numbers | ||
41 | * (gb) - Identify version on module load. | ||
42 | * v1.21.1 (fl) - added Graphire2 support | ||
43 | * v1.21.2 (fl) - added Intuos2 support | ||
44 | * - added all the PL ids | ||
45 | * v1.21.3 (fl) - added another eraser id from Neil Okamoto | ||
46 | * - added smooth filter for Graphire from Peri Hankey | ||
47 | * - added PenPartner support from Olaf van Es | ||
48 | * - new tool ids from Ole Martin Bjoerndalen | ||
49 | * v1.29 (pc) - Add support for more tablets | ||
50 | * - Fix pressure reporting | ||
51 | * v1.30 (vp) - Merge 2.4 and 2.5 drivers | ||
52 | * - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse | ||
53 | * - Cleanups here and there | ||
54 | * v1.30.1 (pi) - Added Graphire3 support | ||
55 | * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... | ||
56 | * v1.43 (pc) - Added support for Cintiq 21UX | ||
57 | * - Fixed a Graphire bug | ||
58 | * - Merged wacom_intuos3_irq into wacom_intuos_irq | ||
59 | * v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc. | ||
60 | * - Report Device IDs | ||
61 | * v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19 | ||
62 | * - Minor data report fix | ||
63 | * v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c, | ||
64 | * - where wacom_sys.c deals with system specific code, | ||
65 | * - and wacom_wac.c deals with Wacom specific code | ||
66 | * - Support Intuos3 4x6 | ||
67 | */ | ||
68 | |||
69 | /* | ||
70 | * This program is free software; you can redistribute it and/or modify | ||
71 | * it under the terms of the GNU General Public License as published by | ||
72 | * the Free Software Foundation; either version 2 of the License, or | ||
73 | * (at your option) any later version. | ||
74 | */ | ||
75 | #ifndef WACOM_H | ||
76 | #define WACOM_H | ||
77 | #include <linux/kernel.h> | ||
78 | #include <linux/slab.h> | ||
79 | #include <linux/module.h> | ||
80 | #include <linux/init.h> | ||
81 | #include <linux/usb/input.h> | ||
82 | #include <asm/unaligned.h> | ||
83 | |||
84 | /* | ||
85 | * Version Information | ||
86 | */ | ||
87 | #define DRIVER_VERSION "v1.46" | ||
88 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | ||
89 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | ||
90 | #define DRIVER_LICENSE "GPL" | ||
91 | |||
92 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
93 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
94 | MODULE_LICENSE(DRIVER_LICENSE); | ||
95 | |||
96 | #define USB_VENDOR_ID_WACOM 0x056a | ||
97 | |||
98 | struct wacom { | ||
99 | dma_addr_t data_dma; | ||
100 | struct input_dev *dev; | ||
101 | struct usb_device *usbdev; | ||
102 | struct urb *irq; | ||
103 | struct wacom_wac * wacom_wac; | ||
104 | char phys[32]; | ||
105 | }; | ||
106 | |||
107 | struct wacom_combo { | ||
108 | struct wacom * wacom; | ||
109 | struct urb * urb; | ||
110 | }; | ||
111 | |||
112 | extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); | ||
113 | extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data); | ||
114 | extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data); | ||
115 | extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data); | ||
116 | extern void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value); | ||
117 | extern void wacom_input_sync(void *wcombo); | ||
118 | extern void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
119 | extern void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
120 | extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
121 | extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
122 | extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
123 | extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
124 | extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
125 | extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
126 | extern __u16 wacom_le16_to_cpu(unsigned char *data); | ||
127 | extern __u16 wacom_be16_to_cpu(unsigned char *data); | ||
128 | extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id); | ||
129 | extern const struct usb_device_id * get_device_table(void); | ||
130 | |||
131 | #endif | ||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c new file mode 100644 index 000000000000..83bddef66067 --- /dev/null +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * drivers/input/tablet/wacom_sys.c | ||
3 | * | ||
4 | * USB Wacom Graphire and Wacom Intuos tablet support - system specific code | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include "wacom.h" | ||
15 | #include "wacom_wac.h" | ||
16 | |||
17 | #define USB_REQ_GET_REPORT 0x01 | ||
18 | #define USB_REQ_SET_REPORT 0x09 | ||
19 | |||
20 | static int usb_get_report(struct usb_interface *intf, unsigned char type, | ||
21 | unsigned char id, void *buf, int size) | ||
22 | { | ||
23 | return usb_control_msg(interface_to_usbdev(intf), | ||
24 | usb_rcvctrlpipe(interface_to_usbdev(intf), 0), | ||
25 | USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
26 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | ||
27 | buf, size, 100); | ||
28 | } | ||
29 | |||
30 | static int usb_set_report(struct usb_interface *intf, unsigned char type, | ||
31 | unsigned char id, void *buf, int size) | ||
32 | { | ||
33 | return usb_control_msg(interface_to_usbdev(intf), | ||
34 | usb_sndctrlpipe(interface_to_usbdev(intf), 0), | ||
35 | USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
36 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | ||
37 | buf, size, 1000); | ||
38 | } | ||
39 | |||
40 | static struct input_dev * get_input_dev(struct wacom_combo *wcombo) | ||
41 | { | ||
42 | return wcombo->wacom->dev; | ||
43 | } | ||
44 | |||
45 | static void wacom_sys_irq(struct urb *urb) | ||
46 | { | ||
47 | struct wacom *wacom = urb->context; | ||
48 | struct wacom_combo wcombo; | ||
49 | int retval; | ||
50 | |||
51 | switch (urb->status) { | ||
52 | case 0: | ||
53 | /* success */ | ||
54 | break; | ||
55 | case -ECONNRESET: | ||
56 | case -ENOENT: | ||
57 | case -ESHUTDOWN: | ||
58 | /* this urb is terminated, clean up */ | ||
59 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
60 | return; | ||
61 | default: | ||
62 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
63 | goto exit; | ||
64 | } | ||
65 | |||
66 | wcombo.wacom = wacom; | ||
67 | wcombo.urb = urb; | ||
68 | |||
69 | if (wacom_wac_irq(wacom->wacom_wac, (void *)&wcombo)) | ||
70 | input_sync(get_input_dev(&wcombo)); | ||
71 | |||
72 | exit: | ||
73 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
74 | if (retval) | ||
75 | err ("%s - usb_submit_urb failed with result %d", | ||
76 | __FUNCTION__, retval); | ||
77 | } | ||
78 | |||
79 | void wacom_report_key(void *wcombo, unsigned int key_type, int key_data) | ||
80 | { | ||
81 | input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data); | ||
82 | return; | ||
83 | } | ||
84 | |||
85 | void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data) | ||
86 | { | ||
87 | input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data) | ||
92 | { | ||
93 | input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data); | ||
94 | return; | ||
95 | } | ||
96 | |||
97 | void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value) | ||
98 | { | ||
99 | input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value); | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | __u16 wacom_be16_to_cpu(unsigned char *data) | ||
104 | { | ||
105 | __u16 value; | ||
106 | value = be16_to_cpu(*(__be16 *) data); | ||
107 | return value; | ||
108 | } | ||
109 | |||
110 | __u16 wacom_le16_to_cpu(unsigned char *data) | ||
111 | { | ||
112 | __u16 value; | ||
113 | value = le16_to_cpu(*(__le16 *) data); | ||
114 | return value; | ||
115 | } | ||
116 | |||
117 | void wacom_input_sync(void *wcombo) | ||
118 | { | ||
119 | input_sync(get_input_dev((struct wacom_combo *)wcombo)); | ||
120 | return; | ||
121 | } | ||
122 | |||
123 | static int wacom_open(struct input_dev *dev) | ||
124 | { | ||
125 | struct wacom *wacom = input_get_drvdata(dev); | ||
126 | |||
127 | wacom->irq->dev = wacom->usbdev; | ||
128 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) | ||
129 | return -EIO; | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static void wacom_close(struct input_dev *dev) | ||
135 | { | ||
136 | struct wacom *wacom = input_get_drvdata(dev); | ||
137 | |||
138 | usb_kill_urb(wacom->irq); | ||
139 | } | ||
140 | |||
141 | void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
142 | { | ||
143 | input_dev->evbit[0] |= BIT(EV_MSC); | ||
144 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | ||
145 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | ||
146 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_4); | ||
147 | } | ||
148 | |||
149 | void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
150 | { | ||
151 | input_dev->evbit[0] |= BIT(EV_REL); | ||
152 | input_dev->relbit[0] |= BIT(REL_WHEEL); | ||
153 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
154 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); | ||
155 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); | ||
156 | } | ||
157 | |||
158 | void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
159 | { | ||
160 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | ||
161 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3); | ||
162 | input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); | ||
163 | } | ||
164 | |||
165 | void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
166 | { | ||
167 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); | ||
168 | input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); | ||
169 | } | ||
170 | |||
171 | void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
172 | { | ||
173 | input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); | ||
174 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | ||
175 | input_dev->relbit[0] |= BIT(REL_WHEEL); | ||
176 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); | ||
177 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) | ||
178 | | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); | ||
179 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); | ||
180 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); | ||
181 | input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); | ||
182 | input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); | ||
183 | input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); | ||
184 | input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); | ||
185 | } | ||
186 | |||
187 | void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
188 | { | ||
189 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); | ||
190 | } | ||
191 | |||
192 | void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
193 | { | ||
194 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER); | ||
195 | } | ||
196 | |||
197 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
198 | { | ||
199 | struct usb_device *dev = interface_to_usbdev(intf); | ||
200 | struct usb_endpoint_descriptor *endpoint; | ||
201 | struct wacom *wacom; | ||
202 | struct wacom_wac *wacom_wac; | ||
203 | struct input_dev *input_dev; | ||
204 | int error = -ENOMEM; | ||
205 | char rep_data[2], limit = 0; | ||
206 | |||
207 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); | ||
208 | wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); | ||
209 | input_dev = input_allocate_device(); | ||
210 | if (!wacom || !input_dev || !wacom_wac) | ||
211 | goto fail1; | ||
212 | |||
213 | wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); | ||
214 | if (!wacom_wac->data) | ||
215 | goto fail1; | ||
216 | |||
217 | wacom->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
218 | if (!wacom->irq) | ||
219 | goto fail2; | ||
220 | |||
221 | wacom->usbdev = dev; | ||
222 | wacom->dev = input_dev; | ||
223 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); | ||
224 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); | ||
225 | |||
226 | wacom_wac->features = get_wacom_feature(id); | ||
227 | BUG_ON(wacom_wac->features->pktlen > 10); | ||
228 | |||
229 | input_dev->name = wacom_wac->features->name; | ||
230 | wacom->wacom_wac = wacom_wac; | ||
231 | usb_to_input_id(dev, &input_dev->id); | ||
232 | |||
233 | input_dev->dev.parent = &intf->dev; | ||
234 | |||
235 | input_set_drvdata(input_dev, wacom); | ||
236 | |||
237 | input_dev->open = wacom_open; | ||
238 | input_dev->close = wacom_close; | ||
239 | |||
240 | input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS); | ||
241 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); | ||
242 | input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0); | ||
243 | input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0); | ||
244 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0); | ||
245 | input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC); | ||
246 | |||
247 | wacom_init_input_dev(input_dev, wacom_wac); | ||
248 | |||
249 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | ||
250 | |||
251 | usb_fill_int_urb(wacom->irq, dev, | ||
252 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | ||
253 | wacom_wac->data, wacom_wac->features->pktlen, | ||
254 | wacom_sys_irq, wacom, endpoint->bInterval); | ||
255 | wacom->irq->transfer_dma = wacom->data_dma; | ||
256 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
257 | |||
258 | error = input_register_device(wacom->dev); | ||
259 | if (error) | ||
260 | goto fail3; | ||
261 | |||
262 | /* Ask the tablet to report tablet data. Repeat until it succeeds */ | ||
263 | do { | ||
264 | rep_data[0] = 2; | ||
265 | rep_data[1] = 2; | ||
266 | usb_set_report(intf, 3, 2, rep_data, 2); | ||
267 | usb_get_report(intf, 3, 2, rep_data, 2); | ||
268 | } while (rep_data[1] != 2 && limit++ < 5); | ||
269 | |||
270 | usb_set_intfdata(intf, wacom); | ||
271 | return 0; | ||
272 | |||
273 | fail3: usb_free_urb(wacom->irq); | ||
274 | fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma); | ||
275 | fail1: input_free_device(input_dev); | ||
276 | kfree(wacom); | ||
277 | kfree(wacom_wac); | ||
278 | return error; | ||
279 | } | ||
280 | |||
281 | static void wacom_disconnect(struct usb_interface *intf) | ||
282 | { | ||
283 | struct wacom *wacom = usb_get_intfdata (intf); | ||
284 | |||
285 | usb_set_intfdata(intf, NULL); | ||
286 | if (wacom) { | ||
287 | usb_kill_urb(wacom->irq); | ||
288 | input_unregister_device(wacom->dev); | ||
289 | usb_free_urb(wacom->irq); | ||
290 | usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma); | ||
291 | kfree(wacom->wacom_wac); | ||
292 | kfree(wacom); | ||
293 | } | ||
294 | } | ||
295 | |||
296 | static struct usb_driver wacom_driver = { | ||
297 | .name = "wacom", | ||
298 | .probe = wacom_probe, | ||
299 | .disconnect = wacom_disconnect, | ||
300 | }; | ||
301 | |||
302 | static int __init wacom_init(void) | ||
303 | { | ||
304 | int result; | ||
305 | wacom_driver.id_table = get_device_table(); | ||
306 | result = usb_register(&wacom_driver); | ||
307 | if (result == 0) | ||
308 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
309 | return result; | ||
310 | } | ||
311 | |||
312 | static void __exit wacom_exit(void) | ||
313 | { | ||
314 | usb_deregister(&wacom_driver); | ||
315 | } | ||
316 | |||
317 | module_init(wacom_init); | ||
318 | module_exit(wacom_exit); | ||
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c new file mode 100644 index 000000000000..7661f03a2db2 --- /dev/null +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -0,0 +1,675 @@ | |||
1 | /* | ||
2 | * drivers/input/tablet/wacom_wac.c | ||
3 | * | ||
4 | * USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | #include "wacom.h" | ||
15 | #include "wacom_wac.h" | ||
16 | |||
17 | static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) | ||
18 | { | ||
19 | unsigned char *data = wacom->data; | ||
20 | |||
21 | switch (data[0]) { | ||
22 | case 1: | ||
23 | if (data[5] & 0x80) { | ||
24 | wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
25 | wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID; | ||
26 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
27 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | ||
28 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | ||
29 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | ||
30 | wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); | ||
31 | wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127)); | ||
32 | wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); | ||
33 | } else { | ||
34 | wacom_report_key(wcombo, wacom->tool[0], 0); | ||
35 | wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */ | ||
36 | wacom_report_abs(wcombo, ABS_PRESSURE, -1); | ||
37 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
38 | } | ||
39 | break; | ||
40 | case 2: | ||
41 | wacom_report_key(wcombo, BTN_TOOL_PEN, 1); | ||
42 | wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ | ||
43 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | ||
44 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | ||
45 | wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); | ||
46 | wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); | ||
47 | wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); | ||
48 | break; | ||
49 | default: | ||
50 | printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); | ||
51 | return 0; | ||
52 | } | ||
53 | return 1; | ||
54 | } | ||
55 | |||
56 | static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) | ||
57 | { | ||
58 | unsigned char *data = wacom->data; | ||
59 | int prox, id, pressure; | ||
60 | |||
61 | if (data[0] != 2) { | ||
62 | dbg("wacom_pl_irq: received unknown report #%d", data[0]); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | prox = data[1] & 0x40; | ||
67 | |||
68 | id = ERASER_DEVICE_ID; | ||
69 | if (prox) { | ||
70 | |||
71 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | ||
72 | if (wacom->features->pressure_max > 255) | ||
73 | pressure = (pressure << 1) | ((data[4] >> 6) & 1); | ||
74 | pressure += (wacom->features->pressure_max + 1) / 2; | ||
75 | |||
76 | /* | ||
77 | * if going from out of proximity into proximity select between the eraser | ||
78 | * and the pen based on the state of the stylus2 button, choose eraser if | ||
79 | * pressed else choose pen. if not a proximity change from out to in, send | ||
80 | * an out of proximity for previous tool then a in for new tool. | ||
81 | */ | ||
82 | if (!wacom->tool[0]) { | ||
83 | /* Eraser bit set for DTF */ | ||
84 | if (data[1] & 0x10) | ||
85 | wacom->tool[1] = BTN_TOOL_RUBBER; | ||
86 | else | ||
87 | /* Going into proximity select tool */ | ||
88 | wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
89 | } else { | ||
90 | /* was entered with stylus2 pressed */ | ||
91 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) { | ||
92 | /* report out proximity for previous tool */ | ||
93 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
94 | wacom_input_sync(wcombo); | ||
95 | wacom->tool[1] = BTN_TOOL_PEN; | ||
96 | return 0; | ||
97 | } | ||
98 | } | ||
99 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | ||
100 | /* Unknown tool selected default to pen tool */ | ||
101 | wacom->tool[1] = BTN_TOOL_PEN; | ||
102 | id = STYLUS_DEVICE_ID; | ||
103 | } | ||
104 | wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */ | ||
105 | wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ | ||
106 | wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); | ||
107 | wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); | ||
108 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); | ||
109 | |||
110 | wacom_report_key(wcombo, BTN_TOUCH, data[4] & 0x08); | ||
111 | wacom_report_key(wcombo, BTN_STYLUS, data[4] & 0x10); | ||
112 | /* Only allow the stylus2 button to be reported for the pen tool. */ | ||
113 | wacom_report_key(wcombo, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); | ||
114 | } else { | ||
115 | /* report proximity-out of a (valid) tool */ | ||
116 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | ||
117 | /* Unknown tool selected default to pen tool */ | ||
118 | wacom->tool[1] = BTN_TOOL_PEN; | ||
119 | } | ||
120 | wacom_report_key(wcombo, wacom->tool[1], prox); | ||
121 | } | ||
122 | |||
123 | wacom->tool[0] = prox; /* Save proximity state */ | ||
124 | return 1; | ||
125 | } | ||
126 | |||
127 | static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) | ||
128 | { | ||
129 | unsigned char *data = wacom->data; | ||
130 | int id; | ||
131 | |||
132 | if (data[0] != 2) { | ||
133 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | if (data[1] & 0x04) { | ||
138 | wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20); | ||
139 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08); | ||
140 | id = ERASER_DEVICE_ID; | ||
141 | } else { | ||
142 | wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20); | ||
143 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); | ||
144 | id = STYLUS_DEVICE_ID; | ||
145 | } | ||
146 | wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ | ||
147 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | ||
148 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
149 | wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | ||
150 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | ||
151 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); | ||
152 | return 1; | ||
153 | } | ||
154 | |||
155 | static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | ||
156 | { | ||
157 | unsigned char *data = wacom->data; | ||
158 | int x, y, id, rw; | ||
159 | |||
160 | if (data[0] != 2) { | ||
161 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | id = STYLUS_DEVICE_ID; | ||
166 | if (data[1] & 0x80) { /* in prox */ | ||
167 | |||
168 | switch ((data[1] >> 5) & 3) { | ||
169 | |||
170 | case 0: /* Pen */ | ||
171 | wacom->tool[0] = BTN_TOOL_PEN; | ||
172 | break; | ||
173 | |||
174 | case 1: /* Rubber */ | ||
175 | wacom->tool[0] = BTN_TOOL_RUBBER; | ||
176 | id = ERASER_DEVICE_ID; | ||
177 | break; | ||
178 | |||
179 | case 2: /* Mouse with wheel */ | ||
180 | wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); | ||
181 | if (wacom->features->type == WACOM_G4) { | ||
182 | rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); | ||
183 | wacom_report_rel(wcombo, REL_WHEEL, -rw); | ||
184 | } else | ||
185 | wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]); | ||
186 | /* fall through */ | ||
187 | |||
188 | case 3: /* Mouse without wheel */ | ||
189 | wacom->tool[0] = BTN_TOOL_MOUSE; | ||
190 | id = CURSOR_DEVICE_ID; | ||
191 | wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); | ||
192 | wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); | ||
193 | if (wacom->features->type == WACOM_G4) | ||
194 | wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); | ||
195 | else | ||
196 | wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); | ||
197 | break; | ||
198 | } | ||
199 | x = wacom_le16_to_cpu(&data[2]); | ||
200 | y = wacom_le16_to_cpu(&data[4]); | ||
201 | wacom_report_abs(wcombo, ABS_X, x); | ||
202 | wacom_report_abs(wcombo, ABS_Y, y); | ||
203 | if (wacom->tool[0] != BTN_TOOL_MOUSE) { | ||
204 | wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); | ||
205 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); | ||
206 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | ||
207 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); | ||
208 | } | ||
209 | wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ | ||
210 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
211 | } else if (!(data[1] & 0x90)) { | ||
212 | wacom_report_abs(wcombo, ABS_X, 0); | ||
213 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
214 | if (wacom->tool[0] == BTN_TOOL_MOUSE) { | ||
215 | wacom_report_key(wcombo, BTN_LEFT, 0); | ||
216 | wacom_report_key(wcombo, BTN_RIGHT, 0); | ||
217 | wacom_report_abs(wcombo, ABS_DISTANCE, 0); | ||
218 | } else { | ||
219 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | ||
220 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
221 | wacom_report_key(wcombo, BTN_STYLUS, 0); | ||
222 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | ||
223 | } | ||
224 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | ||
225 | wacom_report_key(wcombo, wacom->tool[0], 0); | ||
226 | } | ||
227 | |||
228 | /* send pad data */ | ||
229 | if (wacom->features->type == WACOM_G4) { | ||
230 | if (data[7] & 0xf8) { | ||
231 | wacom_input_sync(wcombo); /* sync last event */ | ||
232 | wacom->id[1] = 1; | ||
233 | wacom->serial[1] = (data[7] & 0xf8); | ||
234 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | ||
235 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | ||
236 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); | ||
237 | wacom_report_rel(wcombo, REL_WHEEL, rw); | ||
238 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | ||
239 | wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | ||
240 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
241 | } else if (wacom->id[1]) { | ||
242 | wacom_input_sync(wcombo); /* sync last event */ | ||
243 | wacom->id[1] = 0; | ||
244 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | ||
245 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | ||
246 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | ||
247 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
248 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
249 | } | ||
250 | } | ||
251 | return 1; | ||
252 | } | ||
253 | |||
254 | static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | ||
255 | { | ||
256 | unsigned char *data = wacom->data; | ||
257 | int idx; | ||
258 | |||
259 | /* tool number */ | ||
260 | idx = data[1] & 0x01; | ||
261 | |||
262 | /* Enter report */ | ||
263 | if ((data[1] & 0xfc) == 0xc0) { | ||
264 | /* serial number of the tool */ | ||
265 | wacom->serial[idx] = ((data[3] & 0x0f) << 28) + | ||
266 | (data[4] << 20) + (data[5] << 12) + | ||
267 | (data[6] << 4) + (data[7] >> 4); | ||
268 | |||
269 | wacom->id[idx] = (data[2] << 4) | (data[3] >> 4); | ||
270 | switch (wacom->id[idx]) { | ||
271 | case 0x812: /* Inking pen */ | ||
272 | case 0x801: /* Intuos3 Inking pen */ | ||
273 | case 0x012: | ||
274 | wacom->tool[idx] = BTN_TOOL_PENCIL; | ||
275 | break; | ||
276 | case 0x822: /* Pen */ | ||
277 | case 0x842: | ||
278 | case 0x852: | ||
279 | case 0x823: /* Intuos3 Grip Pen */ | ||
280 | case 0x813: /* Intuos3 Classic Pen */ | ||
281 | case 0x885: /* Intuos3 Marker Pen */ | ||
282 | case 0x022: | ||
283 | wacom->tool[idx] = BTN_TOOL_PEN; | ||
284 | break; | ||
285 | case 0x832: /* Stroke pen */ | ||
286 | case 0x032: | ||
287 | wacom->tool[idx] = BTN_TOOL_BRUSH; | ||
288 | break; | ||
289 | case 0x007: /* Mouse 4D and 2D */ | ||
290 | case 0x09c: | ||
291 | case 0x094: | ||
292 | case 0x017: /* Intuos3 2D Mouse */ | ||
293 | wacom->tool[idx] = BTN_TOOL_MOUSE; | ||
294 | break; | ||
295 | case 0x096: /* Lens cursor */ | ||
296 | case 0x097: /* Intuos3 Lens cursor */ | ||
297 | wacom->tool[idx] = BTN_TOOL_LENS; | ||
298 | break; | ||
299 | case 0x82a: /* Eraser */ | ||
300 | case 0x85a: | ||
301 | case 0x91a: | ||
302 | case 0xd1a: | ||
303 | case 0x0fa: | ||
304 | case 0x82b: /* Intuos3 Grip Pen Eraser */ | ||
305 | case 0x81b: /* Intuos3 Classic Pen Eraser */ | ||
306 | case 0x91b: /* Intuos3 Airbrush Eraser */ | ||
307 | wacom->tool[idx] = BTN_TOOL_RUBBER; | ||
308 | break; | ||
309 | case 0xd12: | ||
310 | case 0x912: | ||
311 | case 0x112: | ||
312 | case 0x913: /* Intuos3 Airbrush */ | ||
313 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; | ||
314 | break; | ||
315 | default: /* Unknown tool */ | ||
316 | wacom->tool[idx] = BTN_TOOL_PEN; | ||
317 | } | ||
318 | return 1; | ||
319 | } | ||
320 | |||
321 | /* Exit report */ | ||
322 | if ((data[1] & 0xfe) == 0x80) { | ||
323 | wacom_report_abs(wcombo, ABS_X, 0); | ||
324 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
325 | wacom_report_abs(wcombo, ABS_DISTANCE, 0); | ||
326 | if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { | ||
327 | wacom_report_key(wcombo, BTN_LEFT, 0); | ||
328 | wacom_report_key(wcombo, BTN_MIDDLE, 0); | ||
329 | wacom_report_key(wcombo, BTN_RIGHT, 0); | ||
330 | wacom_report_key(wcombo, BTN_SIDE, 0); | ||
331 | wacom_report_key(wcombo, BTN_EXTRA, 0); | ||
332 | wacom_report_abs(wcombo, ABS_THROTTLE, 0); | ||
333 | wacom_report_abs(wcombo, ABS_RZ, 0); | ||
334 | } else { | ||
335 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | ||
336 | wacom_report_abs(wcombo, ABS_TILT_X, 0); | ||
337 | wacom_report_abs(wcombo, ABS_TILT_Y, 0); | ||
338 | wacom_report_key(wcombo, BTN_STYLUS, 0); | ||
339 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | ||
340 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
341 | wacom_report_abs(wcombo, ABS_WHEEL, 0); | ||
342 | } | ||
343 | wacom_report_key(wcombo, wacom->tool[idx], 0); | ||
344 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | ||
345 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
346 | return 2; | ||
347 | } | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) | ||
352 | { | ||
353 | unsigned char *data = wacom->data; | ||
354 | unsigned int t; | ||
355 | |||
356 | /* general pen packet */ | ||
357 | if ((data[1] & 0xb8) == 0xa0) { | ||
358 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | ||
359 | wacom_report_abs(wcombo, ABS_PRESSURE, t); | ||
360 | wacom_report_abs(wcombo, ABS_TILT_X, | ||
361 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | ||
362 | wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); | ||
363 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 2); | ||
364 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 4); | ||
365 | wacom_report_key(wcombo, BTN_TOUCH, t > 10); | ||
366 | } | ||
367 | |||
368 | /* airbrush second packet */ | ||
369 | if ((data[1] & 0xbc) == 0xb4) { | ||
370 | wacom_report_abs(wcombo, ABS_WHEEL, | ||
371 | (data[6] << 2) | ((data[7] >> 6) & 3)); | ||
372 | wacom_report_abs(wcombo, ABS_TILT_X, | ||
373 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | ||
374 | wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); | ||
375 | } | ||
376 | return; | ||
377 | } | ||
378 | |||
379 | static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | ||
380 | { | ||
381 | unsigned char *data = wacom->data; | ||
382 | unsigned int t; | ||
383 | int idx, result; | ||
384 | |||
385 | if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { | ||
386 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); | ||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | /* tool number */ | ||
391 | idx = data[1] & 0x01; | ||
392 | |||
393 | /* pad packets. Works as a second tool and is always in prox */ | ||
394 | if (data[0] == 12) { | ||
395 | /* initiate the pad as a device */ | ||
396 | if (wacom->tool[1] != BTN_TOOL_FINGER) | ||
397 | wacom->tool[1] = BTN_TOOL_FINGER; | ||
398 | |||
399 | wacom_report_key(wcombo, BTN_0, (data[5] & 0x01)); | ||
400 | wacom_report_key(wcombo, BTN_1, (data[5] & 0x02)); | ||
401 | wacom_report_key(wcombo, BTN_2, (data[5] & 0x04)); | ||
402 | wacom_report_key(wcombo, BTN_3, (data[5] & 0x08)); | ||
403 | wacom_report_key(wcombo, BTN_4, (data[6] & 0x01)); | ||
404 | wacom_report_key(wcombo, BTN_5, (data[6] & 0x02)); | ||
405 | wacom_report_key(wcombo, BTN_6, (data[6] & 0x04)); | ||
406 | wacom_report_key(wcombo, BTN_7, (data[6] & 0x08)); | ||
407 | wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); | ||
408 | wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); | ||
409 | |||
410 | if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | | ||
411 | data[2] | (data[3] & 0x1f) | data[4]) | ||
412 | wacom_report_key(wcombo, wacom->tool[1], 1); | ||
413 | else | ||
414 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
415 | wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | ||
416 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff); | ||
417 | return 1; | ||
418 | } | ||
419 | |||
420 | /* process in/out prox events */ | ||
421 | result = wacom_intuos_inout(wacom, wcombo); | ||
422 | if (result) | ||
423 | return result-1; | ||
424 | |||
425 | /* Only large I3 and I1 & I2 support Lense Cursor */ | ||
426 | if((wacom->tool[idx] == BTN_TOOL_LENS) | ||
427 | && ((wacom->features->type == INTUOS3) | ||
428 | || (wacom->features->type == INTUOS3S))) | ||
429 | return 0; | ||
430 | |||
431 | /* Cintiq doesn't send data when RDY bit isn't set */ | ||
432 | if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) | ||
433 | return 0; | ||
434 | |||
435 | if (wacom->features->type >= INTUOS3S) { | ||
436 | wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); | ||
437 | wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); | ||
438 | wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); | ||
439 | } else { | ||
440 | wacom_report_abs(wcombo, ABS_X, wacom_be16_to_cpu(&data[2])); | ||
441 | wacom_report_abs(wcombo, ABS_Y, wacom_be16_to_cpu(&data[4])); | ||
442 | wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); | ||
443 | } | ||
444 | |||
445 | /* process general packets */ | ||
446 | wacom_intuos_general(wacom, wcombo); | ||
447 | |||
448 | /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */ | ||
449 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { | ||
450 | |||
451 | if (data[1] & 0x02) { | ||
452 | /* Rotation packet */ | ||
453 | if (wacom->features->type >= INTUOS3S) { | ||
454 | /* I3 marker pen rotation reported as wheel | ||
455 | * due to valuator limitation | ||
456 | */ | ||
457 | t = (data[6] << 3) | ((data[7] >> 5) & 7); | ||
458 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : | ||
459 | ((t-1) / 2 + 450)) : (450 - t / 2) ; | ||
460 | wacom_report_abs(wcombo, ABS_WHEEL, t); | ||
461 | } else { | ||
462 | /* 4D mouse rotation packet */ | ||
463 | t = (data[6] << 3) | ((data[7] >> 5) & 7); | ||
464 | wacom_report_abs(wcombo, ABS_RZ, (data[7] & 0x20) ? | ||
465 | ((t - 1) / 2) : -t / 2); | ||
466 | } | ||
467 | |||
468 | } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3S) { | ||
469 | /* 4D mouse packet */ | ||
470 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); | ||
471 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); | ||
472 | wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x04); | ||
473 | |||
474 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x20); | ||
475 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x10); | ||
476 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | ||
477 | wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | ||
478 | |||
479 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { | ||
480 | /* 2D mouse packet */ | ||
481 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x04); | ||
482 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08); | ||
483 | wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x10); | ||
484 | wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01) | ||
485 | - ((data[8] & 0x02) >> 1)); | ||
486 | |||
487 | /* I3 2D mouse side buttons */ | ||
488 | if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) { | ||
489 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); | ||
490 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); | ||
491 | } | ||
492 | |||
493 | } else if (wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L) { | ||
494 | /* Lens cursor packets */ | ||
495 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); | ||
496 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); | ||
497 | wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x04); | ||
498 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x10); | ||
499 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x08); | ||
500 | } | ||
501 | } | ||
502 | |||
503 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */ | ||
504 | wacom_report_key(wcombo, wacom->tool[idx], 1); | ||
505 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
506 | return 1; | ||
507 | } | ||
508 | |||
509 | int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | ||
510 | { | ||
511 | switch (wacom_wac->features->type) { | ||
512 | case PENPARTNER: | ||
513 | return (wacom_penpartner_irq(wacom_wac, wcombo)); | ||
514 | break; | ||
515 | case PL: | ||
516 | return (wacom_pl_irq(wacom_wac, wcombo)); | ||
517 | break; | ||
518 | case WACOM_G4: | ||
519 | case GRAPHIRE: | ||
520 | return (wacom_graphire_irq(wacom_wac, wcombo)); | ||
521 | break; | ||
522 | case PTU: | ||
523 | return (wacom_ptu_irq(wacom_wac, wcombo)); | ||
524 | break; | ||
525 | case INTUOS: | ||
526 | case INTUOS3S: | ||
527 | case INTUOS3: | ||
528 | case INTUOS3L: | ||
529 | case CINTIQ: | ||
530 | return (wacom_intuos_irq(wacom_wac, wcombo)); | ||
531 | break; | ||
532 | default: | ||
533 | return 0; | ||
534 | } | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
539 | { | ||
540 | switch (wacom_wac->features->type) { | ||
541 | case WACOM_G4: | ||
542 | input_dev_g4(input_dev, wacom_wac); | ||
543 | /* fall through */ | ||
544 | case GRAPHIRE: | ||
545 | input_dev_g(input_dev, wacom_wac); | ||
546 | break; | ||
547 | case INTUOS3: | ||
548 | case INTUOS3L: | ||
549 | case CINTIQ: | ||
550 | input_dev_i3(input_dev, wacom_wac); | ||
551 | /* fall through */ | ||
552 | case INTUOS3S: | ||
553 | input_dev_i3s(input_dev, wacom_wac); | ||
554 | case INTUOS: | ||
555 | input_dev_i(input_dev, wacom_wac); | ||
556 | break; | ||
557 | case PL: | ||
558 | case PTU: | ||
559 | input_dev_pl(input_dev, wacom_wac); | ||
560 | break; | ||
561 | case PENPARTNER: | ||
562 | input_dev_pt(input_dev, wacom_wac); | ||
563 | break; | ||
564 | } | ||
565 | return; | ||
566 | } | ||
567 | |||
568 | static struct wacom_features wacom_features[] = { | ||
569 | { "Wacom Penpartner", 7, 5040, 3780, 255, 0, PENPARTNER }, | ||
570 | { "Wacom Graphire", 8, 10206, 7422, 511, 63, GRAPHIRE }, | ||
571 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 63, GRAPHIRE }, | ||
572 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 63, GRAPHIRE }, | ||
573 | { "Wacom Graphire3", 8, 10208, 7424, 511, 63, GRAPHIRE }, | ||
574 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 63, GRAPHIRE }, | ||
575 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 63, WACOM_G4 }, | ||
576 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 }, | ||
577 | { "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE }, | ||
578 | { "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE }, | ||
579 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE }, | ||
580 | { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE }, | ||
581 | { "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE }, | ||
582 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, | ||
583 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | ||
584 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, | ||
585 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 31, INTUOS }, | ||
586 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 31, INTUOS }, | ||
587 | { "Wacom PL400", 8, 5408, 4056, 255, 0, PL }, | ||
588 | { "Wacom PL500", 8, 6144, 4608, 255, 0, PL }, | ||
589 | { "Wacom PL600", 8, 6126, 4604, 255, 0, PL }, | ||
590 | { "Wacom PL600SX", 8, 6260, 5016, 255, 0, PL }, | ||
591 | { "Wacom PL550", 8, 6144, 4608, 511, 0, PL }, | ||
592 | { "Wacom PL800", 8, 7220, 5780, 511, 0, PL }, | ||
593 | { "Wacom PL700", 8, 6758, 5406, 511, 0, PL }, | ||
594 | { "Wacom PL510", 8, 6282, 4762, 511, 0, PL }, | ||
595 | { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, | ||
596 | { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, | ||
597 | { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, | ||
598 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, | ||
599 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, | ||
600 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | ||
601 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, | ||
602 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS }, | ||
603 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS }, | ||
604 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 63, INTUOS3S }, | ||
605 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 63, INTUOS3 }, | ||
606 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 63, INTUOS3 }, | ||
607 | { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L }, | ||
608 | { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L }, | ||
609 | { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 }, | ||
610 | { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S }, | ||
611 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, | ||
612 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | ||
613 | { } | ||
614 | }; | ||
615 | |||
616 | static struct usb_device_id wacom_ids[] = { | ||
617 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) }, | ||
618 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) }, | ||
619 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) }, | ||
620 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) }, | ||
621 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) }, | ||
622 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) }, | ||
623 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) }, | ||
624 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) }, | ||
625 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, | ||
626 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) }, | ||
627 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, | ||
628 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) }, | ||
629 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) }, | ||
630 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, | ||
631 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, | ||
632 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, | ||
633 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) }, | ||
634 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) }, | ||
635 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) }, | ||
636 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) }, | ||
637 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) }, | ||
638 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) }, | ||
639 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) }, | ||
640 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) }, | ||
641 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, | ||
642 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, | ||
643 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, | ||
644 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, | ||
645 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, | ||
646 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, | ||
647 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, | ||
648 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, | ||
649 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) }, | ||
650 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) }, | ||
651 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) }, | ||
652 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, | ||
653 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, | ||
654 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, | ||
655 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) }, | ||
656 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) }, | ||
657 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, | ||
658 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) }, | ||
659 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, | ||
660 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, | ||
661 | { } | ||
662 | }; | ||
663 | |||
664 | const struct usb_device_id * get_device_table(void) { | ||
665 | const struct usb_device_id * id_table = wacom_ids; | ||
666 | return id_table; | ||
667 | } | ||
668 | |||
669 | struct wacom_features * get_wacom_feature(const struct usb_device_id * id) { | ||
670 | int index = id - wacom_ids; | ||
671 | struct wacom_features *wf = &wacom_features[index]; | ||
672 | return wf; | ||
673 | } | ||
674 | |||
675 | MODULE_DEVICE_TABLE(usb, wacom_ids); | ||
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h new file mode 100644 index 000000000000..a5e12e8756de --- /dev/null +++ b/drivers/input/tablet/wacom_wac.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * drivers/input/tablet/wacom_wac.h | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | */ | ||
9 | #ifndef WACOM_WAC_H | ||
10 | #define WACOM_WAC_H | ||
11 | |||
12 | #define STYLUS_DEVICE_ID 0x02 | ||
13 | #define CURSOR_DEVICE_ID 0x06 | ||
14 | #define ERASER_DEVICE_ID 0x0A | ||
15 | #define PAD_DEVICE_ID 0x0F | ||
16 | |||
17 | enum { | ||
18 | PENPARTNER = 0, | ||
19 | GRAPHIRE, | ||
20 | WACOM_G4, | ||
21 | PTU, | ||
22 | PL, | ||
23 | INTUOS, | ||
24 | INTUOS3S, | ||
25 | INTUOS3, | ||
26 | INTUOS3L, | ||
27 | CINTIQ, | ||
28 | MAX_TYPE | ||
29 | }; | ||
30 | |||
31 | struct wacom_features { | ||
32 | char *name; | ||
33 | int pktlen; | ||
34 | int x_max; | ||
35 | int y_max; | ||
36 | int pressure_max; | ||
37 | int distance_max; | ||
38 | int type; | ||
39 | }; | ||
40 | |||
41 | struct wacom_wac { | ||
42 | unsigned char *data; | ||
43 | int tool[2]; | ||
44 | int id[2]; | ||
45 | __u32 serial[2]; | ||
46 | struct wacom_features *features; | ||
47 | }; | ||
48 | |||
49 | #endif | ||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 971618059a6f..5e640aeb03cd 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | # | 1 | # |
2 | # Mouse driver configuration | 2 | # Touchscreen driver configuration |
3 | # | 3 | # |
4 | menuconfig INPUT_TOUCHSCREEN | 4 | menuconfig INPUT_TOUCHSCREEN |
5 | bool "Touchscreens" | 5 | bool "Touchscreens" |
@@ -44,9 +44,9 @@ config TOUCHSCREEN_BITSY | |||
44 | config TOUCHSCREEN_CORGI | 44 | config TOUCHSCREEN_CORGI |
45 | tristate "SharpSL (Corgi and Spitz series) touchscreen driver" | 45 | tristate "SharpSL (Corgi and Spitz series) touchscreen driver" |
46 | depends on PXA_SHARPSL | 46 | depends on PXA_SHARPSL |
47 | default y | 47 | default y |
48 | help | 48 | help |
49 | Say Y here to enable the driver for the touchscreen on the | 49 | Say Y here to enable the driver for the touchscreen on the |
50 | Sharp SL-C7xx and SL-Cxx00 series of PDAs. | 50 | Sharp SL-C7xx and SL-Cxx00 series of PDAs. |
51 | 51 | ||
52 | If unsure, say N. | 52 | If unsure, say N. |
@@ -164,4 +164,58 @@ config TOUCHSCREEN_UCB1400 | |||
164 | To compile this driver as a module, choose M here: the | 164 | To compile this driver as a module, choose M here: the |
165 | module will be called ucb1400_ts. | 165 | module will be called ucb1400_ts. |
166 | 166 | ||
167 | config TOUCHSCREEN_USB_COMPOSITE | ||
168 | tristate "USB Touchscreen Driver" | ||
169 | select USB | ||
170 | help | ||
171 | USB Touchscreen driver for: | ||
172 | - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700) | ||
173 | - PanJit TouchSet USB | ||
174 | - 3M MicroTouch USB (EX II series) | ||
175 | - ITM | ||
176 | - some other eTurboTouch | ||
177 | - Gunze AHL61 | ||
178 | - DMC TSC-10/25 | ||
179 | |||
180 | Have a look at <http://linux.chapter7.ch/touchkit/> for | ||
181 | a usage description and the required user-space stuff. | ||
182 | |||
183 | To compile this driver as a module, choose M here: the | ||
184 | module will be called usbtouchscreen. | ||
185 | |||
186 | config TOUCHSCREEN_USB_EGALAX | ||
187 | default y | ||
188 | bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED | ||
189 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
190 | |||
191 | config TOUCHSCREEN_USB_PANJIT | ||
192 | default y | ||
193 | bool "PanJit device support" if EMBEDDED | ||
194 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
195 | |||
196 | config TOUCHSCREEN_USB_3M | ||
197 | default y | ||
198 | bool "3M/Microtouch EX II series device support" if EMBEDDED | ||
199 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
200 | |||
201 | config TOUCHSCREEN_USB_ITM | ||
202 | default y | ||
203 | bool "ITM device support" if EMBEDDED | ||
204 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
205 | |||
206 | config TOUCHSCREEN_USB_ETURBO | ||
207 | default y | ||
208 | bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED | ||
209 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
210 | |||
211 | config TOUCHSCREEN_USB_GUNZE | ||
212 | default y | ||
213 | bool "Gunze AHL61 device support" if EMBEDDED | ||
214 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
215 | |||
216 | config TOUCHSCREEN_USB_DMC_TSC10 | ||
217 | default y | ||
218 | bool "DMC TSC-10/25 device support" if EMBEDDED | ||
219 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
220 | |||
167 | endif | 221 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 30e6e2217a15..2f86d6ad06d3 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -1,17 +1,18 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the mouse drivers. | 2 | # Makefile for the touchscreen drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o | 7 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o |
8 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 8 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
9 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o | 9 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o |
10 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 10 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
11 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 11 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
12 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o | 12 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o |
13 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o | 13 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o |
14 | obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o | 14 | obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o |
15 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o | ||
15 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 16 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
16 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 17 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
17 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | 18 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c new file mode 100644 index 000000000000..8e18e6c64777 --- /dev/null +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -0,0 +1,839 @@ | |||
1 | /****************************************************************************** | ||
2 | * usbtouchscreen.c | ||
3 | * Driver for USB Touchscreens, supporting those devices: | ||
4 | * - eGalax Touchkit | ||
5 | * includes eTurboTouch CT-410/510/700 | ||
6 | * - 3M/Microtouch EX II series | ||
7 | * - ITM | ||
8 | * - PanJit TouchSet | ||
9 | * - eTurboTouch | ||
10 | * - Gunze AHL61 | ||
11 | * - DMC TSC-10/25 | ||
12 | * | ||
13 | * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> | ||
14 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or | ||
17 | * modify it under the terms of the GNU General Public License as | ||
18 | * published by the Free Software Foundation; either version 2 of the | ||
19 | * License, or (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, but | ||
22 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
24 | * General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, write to the Free Software | ||
28 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
29 | * | ||
30 | * Driver is based on touchkitusb.c | ||
31 | * - ITM parts are from itmtouch.c | ||
32 | * - 3M parts are from mtouchusb.c | ||
33 | * - PanJit parts are from an unmerged driver by Lanslott Gish | ||
34 | * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged | ||
35 | * driver from Marius Vollmer | ||
36 | * | ||
37 | *****************************************************************************/ | ||
38 | |||
39 | //#define DEBUG | ||
40 | |||
41 | #include <linux/kernel.h> | ||
42 | #include <linux/slab.h> | ||
43 | #include <linux/input.h> | ||
44 | #include <linux/module.h> | ||
45 | #include <linux/init.h> | ||
46 | #include <linux/usb.h> | ||
47 | #include <linux/usb/input.h> | ||
48 | |||
49 | |||
50 | #define DRIVER_VERSION "v0.5" | ||
51 | #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" | ||
52 | #define DRIVER_DESC "USB Touchscreen Driver" | ||
53 | |||
54 | static int swap_xy; | ||
55 | module_param(swap_xy, bool, 0644); | ||
56 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); | ||
57 | |||
58 | /* device specifc data/functions */ | ||
59 | struct usbtouch_usb; | ||
60 | struct usbtouch_device_info { | ||
61 | int min_xc, max_xc; | ||
62 | int min_yc, max_yc; | ||
63 | int min_press, max_press; | ||
64 | int rept_size; | ||
65 | int flags; | ||
66 | |||
67 | void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); | ||
68 | int (*get_pkt_len) (unsigned char *pkt, int len); | ||
69 | int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); | ||
70 | int (*init) (struct usbtouch_usb *usbtouch); | ||
71 | }; | ||
72 | |||
73 | #define USBTOUCH_FLG_BUFFER 0x01 | ||
74 | |||
75 | |||
76 | /* a usbtouch device */ | ||
77 | struct usbtouch_usb { | ||
78 | unsigned char *data; | ||
79 | dma_addr_t data_dma; | ||
80 | unsigned char *buffer; | ||
81 | int buf_len; | ||
82 | struct urb *irq; | ||
83 | struct usb_device *udev; | ||
84 | struct input_dev *input; | ||
85 | struct usbtouch_device_info *type; | ||
86 | char name[128]; | ||
87 | char phys[64]; | ||
88 | |||
89 | int x, y; | ||
90 | int touch, press; | ||
91 | }; | ||
92 | |||
93 | |||
94 | #if defined(CONFIG_USB_TOUCHSCREEN_EGALAX) || defined(CONFIG_USB_TOUCHSCREEN_ETURBO) | ||
95 | #define MULTI_PACKET | ||
96 | #endif | ||
97 | |||
98 | #ifdef MULTI_PACKET | ||
99 | static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, | ||
100 | unsigned char *pkt, int len); | ||
101 | #endif | ||
102 | |||
103 | /* device types */ | ||
104 | enum { | ||
105 | DEVTPYE_DUMMY = -1, | ||
106 | DEVTYPE_EGALAX, | ||
107 | DEVTYPE_PANJIT, | ||
108 | DEVTYPE_3M, | ||
109 | DEVTYPE_ITM, | ||
110 | DEVTYPE_ETURBO, | ||
111 | DEVTYPE_GUNZE, | ||
112 | DEVTYPE_DMC_TSC10, | ||
113 | }; | ||
114 | |||
115 | static struct usb_device_id usbtouch_devices[] = { | ||
116 | #ifdef CONFIG_USB_TOUCHSCREEN_EGALAX | ||
117 | {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, | ||
118 | {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, | ||
119 | {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, | ||
120 | {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, | ||
121 | {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, | ||
122 | {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, | ||
123 | {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, | ||
124 | #endif | ||
125 | |||
126 | #ifdef CONFIG_USB_TOUCHSCREEN_PANJIT | ||
127 | {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, | ||
128 | {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, | ||
129 | {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, | ||
130 | {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, | ||
131 | #endif | ||
132 | |||
133 | #ifdef CONFIG_USB_TOUCHSCREEN_3M | ||
134 | {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, | ||
135 | #endif | ||
136 | |||
137 | #ifdef CONFIG_USB_TOUCHSCREEN_ITM | ||
138 | {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, | ||
139 | #endif | ||
140 | |||
141 | #ifdef CONFIG_USB_TOUCHSCREEN_ETURBO | ||
142 | {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, | ||
143 | #endif | ||
144 | |||
145 | #ifdef CONFIG_USB_TOUCHSCREEN_GUNZE | ||
146 | {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, | ||
147 | #endif | ||
148 | |||
149 | #ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10 | ||
150 | {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, | ||
151 | #endif | ||
152 | |||
153 | {} | ||
154 | }; | ||
155 | |||
156 | |||
157 | /***************************************************************************** | ||
158 | * eGalax part | ||
159 | */ | ||
160 | |||
161 | #ifdef CONFIG_USB_TOUCHSCREEN_EGALAX | ||
162 | |||
163 | #define EGALAX_PKT_TYPE_MASK 0xFE | ||
164 | #define EGALAX_PKT_TYPE_REPT 0x80 | ||
165 | #define EGALAX_PKT_TYPE_DIAG 0x0A | ||
166 | |||
167 | static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
168 | { | ||
169 | if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) | ||
170 | return 0; | ||
171 | |||
172 | dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); | ||
173 | dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); | ||
174 | dev->touch = pkt[0] & 0x01; | ||
175 | |||
176 | return 1; | ||
177 | } | ||
178 | |||
179 | static int egalax_get_pkt_len(unsigned char *buf, int len) | ||
180 | { | ||
181 | switch (buf[0] & EGALAX_PKT_TYPE_MASK) { | ||
182 | case EGALAX_PKT_TYPE_REPT: | ||
183 | return 5; | ||
184 | |||
185 | case EGALAX_PKT_TYPE_DIAG: | ||
186 | if (len < 2) | ||
187 | return -1; | ||
188 | |||
189 | return buf[1] + 2; | ||
190 | } | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | #endif | ||
195 | |||
196 | |||
197 | /***************************************************************************** | ||
198 | * PanJit Part | ||
199 | */ | ||
200 | #ifdef CONFIG_USB_TOUCHSCREEN_PANJIT | ||
201 | static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
202 | { | ||
203 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; | ||
204 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; | ||
205 | dev->touch = pkt[0] & 0x01; | ||
206 | |||
207 | return 1; | ||
208 | } | ||
209 | #endif | ||
210 | |||
211 | |||
212 | /***************************************************************************** | ||
213 | * 3M/Microtouch Part | ||
214 | */ | ||
215 | #ifdef CONFIG_USB_TOUCHSCREEN_3M | ||
216 | |||
217 | #define MTOUCHUSB_ASYNC_REPORT 1 | ||
218 | #define MTOUCHUSB_RESET 7 | ||
219 | #define MTOUCHUSB_REQ_CTRLLR_ID 10 | ||
220 | |||
221 | static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
222 | { | ||
223 | dev->x = (pkt[8] << 8) | pkt[7]; | ||
224 | dev->y = (pkt[10] << 8) | pkt[9]; | ||
225 | dev->touch = (pkt[2] & 0x40) ? 1 : 0; | ||
226 | |||
227 | return 1; | ||
228 | } | ||
229 | |||
230 | static int mtouch_init(struct usbtouch_usb *usbtouch) | ||
231 | { | ||
232 | int ret, i; | ||
233 | |||
234 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | ||
235 | MTOUCHUSB_RESET, | ||
236 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
237 | 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
238 | dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", | ||
239 | __FUNCTION__, ret); | ||
240 | if (ret < 0) | ||
241 | return ret; | ||
242 | msleep(150); | ||
243 | |||
244 | for (i = 0; i < 3; i++) { | ||
245 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | ||
246 | MTOUCHUSB_ASYNC_REPORT, | ||
247 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
248 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
249 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", | ||
250 | __FUNCTION__, ret); | ||
251 | if (ret >= 0) | ||
252 | break; | ||
253 | if (ret != -EPIPE) | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | return 0; | ||
258 | } | ||
259 | #endif | ||
260 | |||
261 | |||
262 | /***************************************************************************** | ||
263 | * ITM Part | ||
264 | */ | ||
265 | #ifdef CONFIG_USB_TOUCHSCREEN_ITM | ||
266 | static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
267 | { | ||
268 | int touch; | ||
269 | /* | ||
270 | * ITM devices report invalid x/y data if not touched. | ||
271 | * if the screen was touched before but is not touched any more | ||
272 | * report touch as 0 with the last valid x/y data once. then stop | ||
273 | * reporting data until touched again. | ||
274 | */ | ||
275 | dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); | ||
276 | |||
277 | touch = ~pkt[7] & 0x20; | ||
278 | if (!touch) { | ||
279 | if (dev->touch) { | ||
280 | dev->touch = 0; | ||
281 | return 1; | ||
282 | } | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); | ||
288 | dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); | ||
289 | dev->touch = touch; | ||
290 | |||
291 | return 1; | ||
292 | } | ||
293 | #endif | ||
294 | |||
295 | |||
296 | /***************************************************************************** | ||
297 | * eTurboTouch part | ||
298 | */ | ||
299 | #ifdef CONFIG_USB_TOUCHSCREEN_ETURBO | ||
300 | static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
301 | { | ||
302 | unsigned int shift; | ||
303 | |||
304 | /* packets should start with sync */ | ||
305 | if (!(pkt[0] & 0x80)) | ||
306 | return 0; | ||
307 | |||
308 | shift = (6 - (pkt[0] & 0x03)); | ||
309 | dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; | ||
310 | dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; | ||
311 | dev->touch = (pkt[0] & 0x10) ? 1 : 0; | ||
312 | |||
313 | return 1; | ||
314 | } | ||
315 | |||
316 | static int eturbo_get_pkt_len(unsigned char *buf, int len) | ||
317 | { | ||
318 | if (buf[0] & 0x80) | ||
319 | return 5; | ||
320 | if (buf[0] == 0x01) | ||
321 | return 3; | ||
322 | return 0; | ||
323 | } | ||
324 | #endif | ||
325 | |||
326 | |||
327 | /***************************************************************************** | ||
328 | * Gunze part | ||
329 | */ | ||
330 | #ifdef CONFIG_USB_TOUCHSCREEN_GUNZE | ||
331 | static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
332 | { | ||
333 | if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) | ||
334 | return 0; | ||
335 | |||
336 | dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); | ||
337 | dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); | ||
338 | dev->touch = pkt[0] & 0x20; | ||
339 | |||
340 | return 1; | ||
341 | } | ||
342 | #endif | ||
343 | |||
344 | /***************************************************************************** | ||
345 | * DMC TSC-10/25 Part | ||
346 | * | ||
347 | * Documentation about the controller and it's protocol can be found at | ||
348 | * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf | ||
349 | * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf | ||
350 | */ | ||
351 | #ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10 | ||
352 | |||
353 | /* supported data rates. currently using 130 */ | ||
354 | #define TSC10_RATE_POINT 0x50 | ||
355 | #define TSC10_RATE_30 0x40 | ||
356 | #define TSC10_RATE_50 0x41 | ||
357 | #define TSC10_RATE_80 0x42 | ||
358 | #define TSC10_RATE_100 0x43 | ||
359 | #define TSC10_RATE_130 0x44 | ||
360 | #define TSC10_RATE_150 0x45 | ||
361 | |||
362 | /* commands */ | ||
363 | #define TSC10_CMD_RESET 0x55 | ||
364 | #define TSC10_CMD_RATE 0x05 | ||
365 | #define TSC10_CMD_DATA1 0x01 | ||
366 | |||
367 | static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) | ||
368 | { | ||
369 | struct usb_device *dev = usbtouch->udev; | ||
370 | int ret; | ||
371 | unsigned char buf[2]; | ||
372 | |||
373 | /* reset */ | ||
374 | buf[0] = buf[1] = 0xFF; | ||
375 | ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), | ||
376 | TSC10_CMD_RESET, | ||
377 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
378 | 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); | ||
379 | if (ret < 0) | ||
380 | return ret; | ||
381 | if (buf[0] != 0x06 || buf[1] != 0x00) | ||
382 | return -ENODEV; | ||
383 | |||
384 | /* set coordinate output rate */ | ||
385 | buf[0] = buf[1] = 0xFF; | ||
386 | ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), | ||
387 | TSC10_CMD_RATE, | ||
388 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
389 | TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); | ||
390 | if (ret < 0) | ||
391 | return ret; | ||
392 | if (buf[0] != 0x06 || buf[1] != 0x00) | ||
393 | return -ENODEV; | ||
394 | |||
395 | /* start sending data */ | ||
396 | ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), | ||
397 | TSC10_CMD_DATA1, | ||
398 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
399 | 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
400 | if (ret < 0) | ||
401 | return ret; | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | |||
407 | static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
408 | { | ||
409 | dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; | ||
410 | dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; | ||
411 | dev->touch = pkt[0] & 0x01; | ||
412 | |||
413 | return 1; | ||
414 | } | ||
415 | #endif | ||
416 | |||
417 | |||
418 | /***************************************************************************** | ||
419 | * the different device descriptors | ||
420 | */ | ||
421 | static struct usbtouch_device_info usbtouch_dev_info[] = { | ||
422 | #ifdef CONFIG_USB_TOUCHSCREEN_EGALAX | ||
423 | [DEVTYPE_EGALAX] = { | ||
424 | .min_xc = 0x0, | ||
425 | .max_xc = 0x07ff, | ||
426 | .min_yc = 0x0, | ||
427 | .max_yc = 0x07ff, | ||
428 | .rept_size = 16, | ||
429 | .flags = USBTOUCH_FLG_BUFFER, | ||
430 | .process_pkt = usbtouch_process_multi, | ||
431 | .get_pkt_len = egalax_get_pkt_len, | ||
432 | .read_data = egalax_read_data, | ||
433 | }, | ||
434 | #endif | ||
435 | |||
436 | #ifdef CONFIG_USB_TOUCHSCREEN_PANJIT | ||
437 | [DEVTYPE_PANJIT] = { | ||
438 | .min_xc = 0x0, | ||
439 | .max_xc = 0x0fff, | ||
440 | .min_yc = 0x0, | ||
441 | .max_yc = 0x0fff, | ||
442 | .rept_size = 8, | ||
443 | .read_data = panjit_read_data, | ||
444 | }, | ||
445 | #endif | ||
446 | |||
447 | #ifdef CONFIG_USB_TOUCHSCREEN_3M | ||
448 | [DEVTYPE_3M] = { | ||
449 | .min_xc = 0x0, | ||
450 | .max_xc = 0x4000, | ||
451 | .min_yc = 0x0, | ||
452 | .max_yc = 0x4000, | ||
453 | .rept_size = 11, | ||
454 | .read_data = mtouch_read_data, | ||
455 | .init = mtouch_init, | ||
456 | }, | ||
457 | #endif | ||
458 | |||
459 | #ifdef CONFIG_USB_TOUCHSCREEN_ITM | ||
460 | [DEVTYPE_ITM] = { | ||
461 | .min_xc = 0x0, | ||
462 | .max_xc = 0x0fff, | ||
463 | .min_yc = 0x0, | ||
464 | .max_yc = 0x0fff, | ||
465 | .max_press = 0xff, | ||
466 | .rept_size = 8, | ||
467 | .read_data = itm_read_data, | ||
468 | }, | ||
469 | #endif | ||
470 | |||
471 | #ifdef CONFIG_USB_TOUCHSCREEN_ETURBO | ||
472 | [DEVTYPE_ETURBO] = { | ||
473 | .min_xc = 0x0, | ||
474 | .max_xc = 0x07ff, | ||
475 | .min_yc = 0x0, | ||
476 | .max_yc = 0x07ff, | ||
477 | .rept_size = 8, | ||
478 | .flags = USBTOUCH_FLG_BUFFER, | ||
479 | .process_pkt = usbtouch_process_multi, | ||
480 | .get_pkt_len = eturbo_get_pkt_len, | ||
481 | .read_data = eturbo_read_data, | ||
482 | }, | ||
483 | #endif | ||
484 | |||
485 | #ifdef CONFIG_USB_TOUCHSCREEN_GUNZE | ||
486 | [DEVTYPE_GUNZE] = { | ||
487 | .min_xc = 0x0, | ||
488 | .max_xc = 0x0fff, | ||
489 | .min_yc = 0x0, | ||
490 | .max_yc = 0x0fff, | ||
491 | .rept_size = 4, | ||
492 | .read_data = gunze_read_data, | ||
493 | }, | ||
494 | #endif | ||
495 | |||
496 | #ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10 | ||
497 | [DEVTYPE_DMC_TSC10] = { | ||
498 | .min_xc = 0x0, | ||
499 | .max_xc = 0x03ff, | ||
500 | .min_yc = 0x0, | ||
501 | .max_yc = 0x03ff, | ||
502 | .rept_size = 5, | ||
503 | .init = dmc_tsc10_init, | ||
504 | .read_data = dmc_tsc10_read_data, | ||
505 | }, | ||
506 | #endif | ||
507 | }; | ||
508 | |||
509 | |||
510 | /***************************************************************************** | ||
511 | * Generic Part | ||
512 | */ | ||
513 | static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, | ||
514 | unsigned char *pkt, int len) | ||
515 | { | ||
516 | struct usbtouch_device_info *type = usbtouch->type; | ||
517 | |||
518 | if (!type->read_data(usbtouch, pkt)) | ||
519 | return; | ||
520 | |||
521 | input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); | ||
522 | |||
523 | if (swap_xy) { | ||
524 | input_report_abs(usbtouch->input, ABS_X, usbtouch->y); | ||
525 | input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); | ||
526 | } else { | ||
527 | input_report_abs(usbtouch->input, ABS_X, usbtouch->x); | ||
528 | input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); | ||
529 | } | ||
530 | if (type->max_press) | ||
531 | input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); | ||
532 | input_sync(usbtouch->input); | ||
533 | } | ||
534 | |||
535 | |||
536 | #ifdef MULTI_PACKET | ||
537 | static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, | ||
538 | unsigned char *pkt, int len) | ||
539 | { | ||
540 | unsigned char *buffer; | ||
541 | int pkt_len, pos, buf_len, tmp; | ||
542 | |||
543 | /* process buffer */ | ||
544 | if (unlikely(usbtouch->buf_len)) { | ||
545 | /* try to get size */ | ||
546 | pkt_len = usbtouch->type->get_pkt_len( | ||
547 | usbtouch->buffer, usbtouch->buf_len); | ||
548 | |||
549 | /* drop? */ | ||
550 | if (unlikely(!pkt_len)) | ||
551 | goto out_flush_buf; | ||
552 | |||
553 | /* need to append -pkt_len bytes before able to get size */ | ||
554 | if (unlikely(pkt_len < 0)) { | ||
555 | int append = -pkt_len; | ||
556 | if (unlikely(append > len)) | ||
557 | append = len; | ||
558 | if (usbtouch->buf_len + append >= usbtouch->type->rept_size) | ||
559 | goto out_flush_buf; | ||
560 | memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); | ||
561 | usbtouch->buf_len += append; | ||
562 | |||
563 | pkt_len = usbtouch->type->get_pkt_len( | ||
564 | usbtouch->buffer, usbtouch->buf_len); | ||
565 | if (pkt_len < 0) | ||
566 | return; | ||
567 | } | ||
568 | |||
569 | /* append */ | ||
570 | tmp = pkt_len - usbtouch->buf_len; | ||
571 | if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) | ||
572 | goto out_flush_buf; | ||
573 | memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); | ||
574 | usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); | ||
575 | |||
576 | buffer = pkt + tmp; | ||
577 | buf_len = len - tmp; | ||
578 | } else { | ||
579 | buffer = pkt; | ||
580 | buf_len = len; | ||
581 | } | ||
582 | |||
583 | /* loop over the received packet, process */ | ||
584 | pos = 0; | ||
585 | while (pos < buf_len) { | ||
586 | /* get packet len */ | ||
587 | pkt_len = usbtouch->type->get_pkt_len(buffer + pos, len); | ||
588 | |||
589 | /* unknown packet: drop everything */ | ||
590 | if (unlikely(!pkt_len)) | ||
591 | goto out_flush_buf; | ||
592 | |||
593 | /* full packet: process */ | ||
594 | if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { | ||
595 | usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); | ||
596 | } else { | ||
597 | /* incomplete packet: save in buffer */ | ||
598 | memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); | ||
599 | usbtouch->buf_len = buf_len - pos; | ||
600 | return; | ||
601 | } | ||
602 | pos += pkt_len; | ||
603 | } | ||
604 | |||
605 | out_flush_buf: | ||
606 | usbtouch->buf_len = 0; | ||
607 | return; | ||
608 | } | ||
609 | #endif | ||
610 | |||
611 | |||
612 | static void usbtouch_irq(struct urb *urb) | ||
613 | { | ||
614 | struct usbtouch_usb *usbtouch = urb->context; | ||
615 | int retval; | ||
616 | |||
617 | switch (urb->status) { | ||
618 | case 0: | ||
619 | /* success */ | ||
620 | break; | ||
621 | case -ETIME: | ||
622 | /* this urb is timing out */ | ||
623 | dbg("%s - urb timed out - was the device unplugged?", | ||
624 | __FUNCTION__); | ||
625 | return; | ||
626 | case -ECONNRESET: | ||
627 | case -ENOENT: | ||
628 | case -ESHUTDOWN: | ||
629 | /* this urb is terminated, clean up */ | ||
630 | dbg("%s - urb shutting down with status: %d", | ||
631 | __FUNCTION__, urb->status); | ||
632 | return; | ||
633 | default: | ||
634 | dbg("%s - nonzero urb status received: %d", | ||
635 | __FUNCTION__, urb->status); | ||
636 | goto exit; | ||
637 | } | ||
638 | |||
639 | usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); | ||
640 | |||
641 | exit: | ||
642 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
643 | if (retval) | ||
644 | err("%s - usb_submit_urb failed with result: %d", | ||
645 | __FUNCTION__, retval); | ||
646 | } | ||
647 | |||
648 | static int usbtouch_open(struct input_dev *input) | ||
649 | { | ||
650 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); | ||
651 | |||
652 | usbtouch->irq->dev = usbtouch->udev; | ||
653 | |||
654 | if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) | ||
655 | return -EIO; | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | static void usbtouch_close(struct input_dev *input) | ||
661 | { | ||
662 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); | ||
663 | |||
664 | usb_kill_urb(usbtouch->irq); | ||
665 | } | ||
666 | |||
667 | |||
668 | static void usbtouch_free_buffers(struct usb_device *udev, | ||
669 | struct usbtouch_usb *usbtouch) | ||
670 | { | ||
671 | usb_buffer_free(udev, usbtouch->type->rept_size, | ||
672 | usbtouch->data, usbtouch->data_dma); | ||
673 | kfree(usbtouch->buffer); | ||
674 | } | ||
675 | |||
676 | |||
677 | static int usbtouch_probe(struct usb_interface *intf, | ||
678 | const struct usb_device_id *id) | ||
679 | { | ||
680 | struct usbtouch_usb *usbtouch; | ||
681 | struct input_dev *input_dev; | ||
682 | struct usb_host_interface *interface; | ||
683 | struct usb_endpoint_descriptor *endpoint; | ||
684 | struct usb_device *udev = interface_to_usbdev(intf); | ||
685 | struct usbtouch_device_info *type; | ||
686 | int err = -ENOMEM; | ||
687 | |||
688 | interface = intf->cur_altsetting; | ||
689 | endpoint = &interface->endpoint[0].desc; | ||
690 | |||
691 | usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); | ||
692 | input_dev = input_allocate_device(); | ||
693 | if (!usbtouch || !input_dev) | ||
694 | goto out_free; | ||
695 | |||
696 | type = &usbtouch_dev_info[id->driver_info]; | ||
697 | usbtouch->type = type; | ||
698 | if (!type->process_pkt) | ||
699 | type->process_pkt = usbtouch_process_pkt; | ||
700 | |||
701 | usbtouch->data = usb_buffer_alloc(udev, type->rept_size, | ||
702 | GFP_KERNEL, &usbtouch->data_dma); | ||
703 | if (!usbtouch->data) | ||
704 | goto out_free; | ||
705 | |||
706 | if (type->flags & USBTOUCH_FLG_BUFFER) { | ||
707 | usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); | ||
708 | if (!usbtouch->buffer) | ||
709 | goto out_free_buffers; | ||
710 | } | ||
711 | |||
712 | usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
713 | if (!usbtouch->irq) { | ||
714 | dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__); | ||
715 | goto out_free_buffers; | ||
716 | } | ||
717 | |||
718 | usbtouch->udev = udev; | ||
719 | usbtouch->input = input_dev; | ||
720 | |||
721 | if (udev->manufacturer) | ||
722 | strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); | ||
723 | |||
724 | if (udev->product) { | ||
725 | if (udev->manufacturer) | ||
726 | strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); | ||
727 | strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); | ||
728 | } | ||
729 | |||
730 | if (!strlen(usbtouch->name)) | ||
731 | snprintf(usbtouch->name, sizeof(usbtouch->name), | ||
732 | "USB Touchscreen %04x:%04x", | ||
733 | le16_to_cpu(udev->descriptor.idVendor), | ||
734 | le16_to_cpu(udev->descriptor.idProduct)); | ||
735 | |||
736 | usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); | ||
737 | strlcpy(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); | ||
738 | |||
739 | input_dev->name = usbtouch->name; | ||
740 | input_dev->phys = usbtouch->phys; | ||
741 | usb_to_input_id(udev, &input_dev->id); | ||
742 | input_dev->dev.parent = &intf->dev; | ||
743 | |||
744 | input_set_drvdata(input_dev, usbtouch); | ||
745 | |||
746 | input_dev->open = usbtouch_open; | ||
747 | input_dev->close = usbtouch_close; | ||
748 | |||
749 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
750 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
751 | input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); | ||
752 | input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); | ||
753 | if (type->max_press) | ||
754 | input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, | ||
755 | type->max_press, 0, 0); | ||
756 | |||
757 | usb_fill_int_urb(usbtouch->irq, usbtouch->udev, | ||
758 | usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress), | ||
759 | usbtouch->data, type->rept_size, | ||
760 | usbtouch_irq, usbtouch, endpoint->bInterval); | ||
761 | |||
762 | usbtouch->irq->dev = usbtouch->udev; | ||
763 | usbtouch->irq->transfer_dma = usbtouch->data_dma; | ||
764 | usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
765 | |||
766 | /* device specific init */ | ||
767 | if (type->init) { | ||
768 | err = type->init(usbtouch); | ||
769 | if (err) { | ||
770 | dbg("%s - type->init() failed, err: %d", __FUNCTION__, err); | ||
771 | goto out_free_buffers; | ||
772 | } | ||
773 | } | ||
774 | |||
775 | err = input_register_device(usbtouch->input); | ||
776 | if (err) { | ||
777 | dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err); | ||
778 | goto out_free_buffers; | ||
779 | } | ||
780 | |||
781 | usb_set_intfdata(intf, usbtouch); | ||
782 | |||
783 | return 0; | ||
784 | |||
785 | out_free_buffers: | ||
786 | usbtouch_free_buffers(udev, usbtouch); | ||
787 | out_free: | ||
788 | input_free_device(input_dev); | ||
789 | kfree(usbtouch); | ||
790 | return err; | ||
791 | } | ||
792 | |||
793 | static void usbtouch_disconnect(struct usb_interface *intf) | ||
794 | { | ||
795 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | ||
796 | |||
797 | dbg("%s - called", __FUNCTION__); | ||
798 | |||
799 | if (!usbtouch) | ||
800 | return; | ||
801 | |||
802 | dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__); | ||
803 | usb_set_intfdata(intf, NULL); | ||
804 | usb_kill_urb(usbtouch->irq); | ||
805 | input_unregister_device(usbtouch->input); | ||
806 | usb_free_urb(usbtouch->irq); | ||
807 | usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); | ||
808 | kfree(usbtouch); | ||
809 | } | ||
810 | |||
811 | MODULE_DEVICE_TABLE(usb, usbtouch_devices); | ||
812 | |||
813 | static struct usb_driver usbtouch_driver = { | ||
814 | .name = "usbtouchscreen", | ||
815 | .probe = usbtouch_probe, | ||
816 | .disconnect = usbtouch_disconnect, | ||
817 | .id_table = usbtouch_devices, | ||
818 | }; | ||
819 | |||
820 | static int __init usbtouch_init(void) | ||
821 | { | ||
822 | return usb_register(&usbtouch_driver); | ||
823 | } | ||
824 | |||
825 | static void __exit usbtouch_cleanup(void) | ||
826 | { | ||
827 | usb_deregister(&usbtouch_driver); | ||
828 | } | ||
829 | |||
830 | module_init(usbtouch_init); | ||
831 | module_exit(usbtouch_cleanup); | ||
832 | |||
833 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
834 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
835 | MODULE_LICENSE("GPL"); | ||
836 | |||
837 | MODULE_ALIAS("touchkitusb"); | ||
838 | MODULE_ALIAS("itmtouch"); | ||
839 | MODULE_ALIAS("mtouchusb"); | ||