diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 11:20:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 11:20:33 -0400 |
commit | a12f66fccf2e266ad197df142b5ebafc6a169a8c (patch) | |
tree | 9d0bc76f8aa9c42fb44ce5f5bf6b4b09f4efafed /drivers | |
parent | 12dce6263d43daeb4e16fa4eb964c1c99fa4fa2e (diff) | |
parent | bb0885900de49b5822d7e8c91c1adf9a0fcc228b (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (35 commits)
Input: wistron - add support for Acer TravelMate 2424NWXCi
Input: wistron - fix setting up special buttons
Input: add KEY_BLUETOOTH and KEY_WLAN definitions
Input: add new BUS_VIRTUAL bus type
Input: add driver for stowaway serial keyboards
Input: make input_register_handler() return error codes
Input: remove cruft that was needed for transition to sysfs
Input: fix input module refcounting
Input: constify input core
Input: libps2 - rearrange exports
Input: atkbd - support Microsoft Natural Elite Pro keyboards
Input: i8042 - disable MUX mode on Toshiba Equium A110
Input: i8042 - get rid of polling timer
Input: send key up events at disconnect
Input: constify psmouse driver
Input: i8042 - add Amoi to the MUX blacklist
Input: logips2pp - add sugnature 56 (Cordless MouseMan Wheel), cleanup
Input: add driver for Touchwin serial touchscreens
Input: add driver for Touchright serial touchscreens
Input: add driver for Penmount serial touchscreens
...
Diffstat (limited to 'drivers')
52 files changed, 4241 insertions, 2037 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 99fb070fdbf8..e2011669c7bb 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -1293,7 +1293,7 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type, | |||
1293 | */ | 1293 | */ |
1294 | static struct input_handle *kbd_connect(struct input_handler *handler, | 1294 | static struct input_handle *kbd_connect(struct input_handler *handler, |
1295 | struct input_dev *dev, | 1295 | struct input_dev *dev, |
1296 | struct input_device_id *id) | 1296 | const struct input_device_id *id) |
1297 | { | 1297 | { |
1298 | struct input_handle *handle; | 1298 | struct input_handle *handle; |
1299 | int i; | 1299 | int i; |
@@ -1342,7 +1342,7 @@ static void kbd_start(struct input_handle *handle) | |||
1342 | tasklet_enable(&keyboard_tasklet); | 1342 | tasklet_enable(&keyboard_tasklet); |
1343 | } | 1343 | } |
1344 | 1344 | ||
1345 | static struct input_device_id kbd_ids[] = { | 1345 | static const struct input_device_id kbd_ids[] = { |
1346 | { | 1346 | { |
1347 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT, | 1347 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT, |
1348 | .evbit = { BIT(EV_KEY) }, | 1348 | .evbit = { BIT(EV_KEY) }, |
@@ -1370,6 +1370,7 @@ static struct input_handler kbd_handler = { | |||
1370 | int __init kbd_init(void) | 1370 | int __init kbd_init(void) |
1371 | { | 1371 | { |
1372 | int i; | 1372 | int i; |
1373 | int error; | ||
1373 | 1374 | ||
1374 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | 1375 | for (i = 0; i < MAX_NR_CONSOLES; i++) { |
1375 | kbd_table[i].ledflagstate = KBD_DEFLEDS; | 1376 | kbd_table[i].ledflagstate = KBD_DEFLEDS; |
@@ -1381,7 +1382,9 @@ int __init kbd_init(void) | |||
1381 | kbd_table[i].kbdmode = VC_XLATE; | 1382 | kbd_table[i].kbdmode = VC_XLATE; |
1382 | } | 1383 | } |
1383 | 1384 | ||
1384 | input_register_handler(&kbd_handler); | 1385 | error = input_register_handler(&kbd_handler); |
1386 | if (error) | ||
1387 | return error; | ||
1385 | 1388 | ||
1386 | tasklet_enable(&keyboard_tasklet); | 1389 | tasklet_enable(&keyboard_tasklet); |
1387 | tasklet_schedule(&keyboard_tasklet); | 1390 | tasklet_schedule(&keyboard_tasklet); |
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 58223b5d842a..96232313b1b9 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig | |||
@@ -24,6 +24,20 @@ config INPUT | |||
24 | 24 | ||
25 | if INPUT | 25 | if INPUT |
26 | 26 | ||
27 | config INPUT_FF_MEMLESS | ||
28 | tristate "Support for memoryless force-feedback devices" | ||
29 | default n | ||
30 | ---help--- | ||
31 | Say Y here if you have memoryless force-feedback input device | ||
32 | such as Logitech WingMan Force 3D, ThrustMaster FireStorm Dual | ||
33 | Power 2, or similar. You will also need to enable hardware-specific | ||
34 | driver. | ||
35 | |||
36 | If unsure, say N. | ||
37 | |||
38 | To compile this driver as a module, choose M here: the | ||
39 | module will be called ff-memless. | ||
40 | |||
27 | comment "Userland interfaces" | 41 | comment "Userland interfaces" |
28 | 42 | ||
29 | config INPUT_MOUSEDEV | 43 | config INPUT_MOUSEDEV |
diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 1a6ff4982f30..a005b1df5f1a 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile | |||
@@ -4,7 +4,11 @@ | |||
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_INPUT) += input.o | 7 | obj-$(CONFIG_INPUT) += input-core.o |
8 | input-core-objs := input.o ff-core.o | ||
9 | |||
10 | obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o | ||
11 | |||
8 | obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o | 12 | obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o |
9 | obj-$(CONFIG_INPUT_JOYDEV) += joydev.o | 13 | obj-$(CONFIG_INPUT_JOYDEV) += joydev.o |
10 | obj-$(CONFIG_INPUT_EVDEV) += evdev.o | 14 | obj-$(CONFIG_INPUT_EVDEV) += evdev.o |
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c index 07358fb51b82..5a9653c3128a 100644 --- a/drivers/input/evbug.c +++ b/drivers/input/evbug.c | |||
@@ -42,10 +42,12 @@ static char evbug_name[] = "evbug"; | |||
42 | 42 | ||
43 | static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 43 | static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) |
44 | { | 44 | { |
45 | printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", handle->dev->phys, type, code, value); | 45 | printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", |
46 | handle->dev->phys, type, code, value); | ||
46 | } | 47 | } |
47 | 48 | ||
48 | static struct input_handle *evbug_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id) | 49 | static struct input_handle *evbug_connect(struct input_handler *handler, struct input_dev *dev, |
50 | const struct input_device_id *id) | ||
49 | { | 51 | { |
50 | struct input_handle *handle; | 52 | struct input_handle *handle; |
51 | 53 | ||
@@ -72,7 +74,7 @@ static void evbug_disconnect(struct input_handle *handle) | |||
72 | kfree(handle); | 74 | kfree(handle); |
73 | } | 75 | } |
74 | 76 | ||
75 | static struct input_device_id evbug_ids[] = { | 77 | static const struct input_device_id evbug_ids[] = { |
76 | { .driver_info = 1 }, /* Matches all devices */ | 78 | { .driver_info = 1 }, /* Matches all devices */ |
77 | { }, /* Terminating zero entry */ | 79 | { }, /* Terminating zero entry */ |
78 | }; | 80 | }; |
@@ -89,8 +91,7 @@ static struct input_handler evbug_handler = { | |||
89 | 91 | ||
90 | static int __init evbug_init(void) | 92 | static int __init evbug_init(void) |
91 | { | 93 | { |
92 | input_register_handler(&evbug_handler); | 94 | return input_register_handler(&evbug_handler); |
93 | return 0; | ||
94 | } | 95 | } |
95 | 96 | ||
96 | static void __exit evbug_exit(void) | 97 | static void __exit evbug_exit(void) |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 4bf48188cc91..6439f378f6cc 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -391,8 +391,10 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | |||
391 | struct evdev *evdev = list->evdev; | 391 | struct evdev *evdev = list->evdev; |
392 | struct input_dev *dev = evdev->handle.dev; | 392 | struct input_dev *dev = evdev->handle.dev; |
393 | struct input_absinfo abs; | 393 | struct input_absinfo abs; |
394 | struct ff_effect effect; | ||
394 | int __user *ip = (int __user *)p; | 395 | int __user *ip = (int __user *)p; |
395 | int i, t, u, v; | 396 | int i, t, u, v; |
397 | int error; | ||
396 | 398 | ||
397 | if (!evdev->exist) | 399 | if (!evdev->exist) |
398 | return -ENODEV; | 400 | return -ENODEV; |
@@ -460,27 +462,22 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | |||
460 | return 0; | 462 | return 0; |
461 | 463 | ||
462 | case EVIOCSFF: | 464 | case EVIOCSFF: |
463 | if (dev->upload_effect) { | 465 | if (copy_from_user(&effect, p, sizeof(effect))) |
464 | struct ff_effect effect; | 466 | return -EFAULT; |
465 | int err; | ||
466 | |||
467 | if (copy_from_user(&effect, p, sizeof(effect))) | ||
468 | return -EFAULT; | ||
469 | err = dev->upload_effect(dev, &effect); | ||
470 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) | ||
471 | return -EFAULT; | ||
472 | return err; | ||
473 | } else | ||
474 | return -ENOSYS; | ||
475 | 467 | ||
476 | case EVIOCRMFF: | 468 | error = input_ff_upload(dev, &effect, file); |
477 | if (!dev->erase_effect) | ||
478 | return -ENOSYS; | ||
479 | 469 | ||
480 | return dev->erase_effect(dev, (int)(unsigned long) p); | 470 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) |
471 | return -EFAULT; | ||
472 | |||
473 | return error; | ||
474 | |||
475 | case EVIOCRMFF: | ||
476 | return input_ff_erase(dev, (int)(unsigned long) p, file); | ||
481 | 477 | ||
482 | case EVIOCGEFFECTS: | 478 | case EVIOCGEFFECTS: |
483 | if (put_user(dev->ff_effects_max, ip)) | 479 | i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0; |
480 | if (put_user(i, ip)) | ||
484 | return -EFAULT; | 481 | return -EFAULT; |
485 | return 0; | 482 | return 0; |
486 | 483 | ||
@@ -604,7 +601,7 @@ static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned lon | |||
604 | } | 601 | } |
605 | #endif | 602 | #endif |
606 | 603 | ||
607 | static struct file_operations evdev_fops = { | 604 | static const struct file_operations evdev_fops = { |
608 | .owner = THIS_MODULE, | 605 | .owner = THIS_MODULE, |
609 | .read = evdev_read, | 606 | .read = evdev_read, |
610 | .write = evdev_write, | 607 | .write = evdev_write, |
@@ -619,7 +616,8 @@ static struct file_operations evdev_fops = { | |||
619 | .flush = evdev_flush | 616 | .flush = evdev_flush |
620 | }; | 617 | }; |
621 | 618 | ||
622 | static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id) | 619 | static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, |
620 | const struct input_device_id *id) | ||
623 | { | 621 | { |
624 | struct evdev *evdev; | 622 | struct evdev *evdev; |
625 | struct class_device *cdev; | 623 | struct class_device *cdev; |
@@ -669,6 +667,7 @@ static void evdev_disconnect(struct input_handle *handle) | |||
669 | evdev->exist = 0; | 667 | evdev->exist = 0; |
670 | 668 | ||
671 | if (evdev->open) { | 669 | if (evdev->open) { |
670 | input_flush_device(handle, NULL); | ||
672 | input_close_device(handle); | 671 | input_close_device(handle); |
673 | wake_up_interruptible(&evdev->wait); | 672 | wake_up_interruptible(&evdev->wait); |
674 | list_for_each_entry(list, &evdev->list, node) | 673 | list_for_each_entry(list, &evdev->list, node) |
@@ -677,7 +676,7 @@ static void evdev_disconnect(struct input_handle *handle) | |||
677 | evdev_free(evdev); | 676 | evdev_free(evdev); |
678 | } | 677 | } |
679 | 678 | ||
680 | static struct input_device_id evdev_ids[] = { | 679 | static const struct input_device_id evdev_ids[] = { |
681 | { .driver_info = 1 }, /* Matches all devices */ | 680 | { .driver_info = 1 }, /* Matches all devices */ |
682 | { }, /* Terminating zero entry */ | 681 | { }, /* Terminating zero entry */ |
683 | }; | 682 | }; |
@@ -696,8 +695,7 @@ static struct input_handler evdev_handler = { | |||
696 | 695 | ||
697 | static int __init evdev_init(void) | 696 | static int __init evdev_init(void) |
698 | { | 697 | { |
699 | input_register_handler(&evdev_handler); | 698 | return input_register_handler(&evdev_handler); |
700 | return 0; | ||
701 | } | 699 | } |
702 | 700 | ||
703 | static void __exit evdev_exit(void) | 701 | static void __exit evdev_exit(void) |
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c new file mode 100644 index 000000000000..35656cadc914 --- /dev/null +++ b/drivers/input/ff-core.c | |||
@@ -0,0 +1,367 @@ | |||
1 | /* | ||
2 | * Force feedback support for Linux input subsystem | ||
3 | * | ||
4 | * Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
5 | * Copyright (c) 2006 Dmitry Torokhov <dtor@mail.ru> | ||
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 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | /* #define DEBUG */ | ||
25 | |||
26 | #define debug(format, arg...) pr_debug("ff-core: " format "\n", ## arg) | ||
27 | |||
28 | #include <linux/input.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/mutex.h> | ||
31 | |||
32 | /* | ||
33 | * Check that the effect_id is a valid effect and whether the user | ||
34 | * is the owner | ||
35 | */ | ||
36 | static int check_effect_access(struct ff_device *ff, int effect_id, | ||
37 | struct file *file) | ||
38 | { | ||
39 | if (effect_id < 0 || effect_id >= ff->max_effects || | ||
40 | !ff->effect_owners[effect_id]) | ||
41 | return -EINVAL; | ||
42 | |||
43 | if (file && ff->effect_owners[effect_id] != file) | ||
44 | return -EACCES; | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | * Checks whether 2 effects can be combined together | ||
51 | */ | ||
52 | static inline int check_effects_compatible(struct ff_effect *e1, | ||
53 | struct ff_effect *e2) | ||
54 | { | ||
55 | return e1->type == e2->type && | ||
56 | (e1->type != FF_PERIODIC || | ||
57 | e1->u.periodic.waveform == e2->u.periodic.waveform); | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * Convert an effect into compatible one | ||
62 | */ | ||
63 | static int compat_effect(struct ff_device *ff, struct ff_effect *effect) | ||
64 | { | ||
65 | int magnitude; | ||
66 | |||
67 | switch (effect->type) { | ||
68 | case FF_RUMBLE: | ||
69 | if (!test_bit(FF_PERIODIC, ff->ffbit)) | ||
70 | return -EINVAL; | ||
71 | |||
72 | /* | ||
73 | * calculate manginude of sine wave as average of rumble's | ||
74 | * 2/3 of strong magnitude and 1/3 of weak magnitude | ||
75 | */ | ||
76 | magnitude = effect->u.rumble.strong_magnitude / 3 + | ||
77 | effect->u.rumble.weak_magnitude / 6; | ||
78 | |||
79 | effect->type = FF_PERIODIC; | ||
80 | effect->u.periodic.waveform = FF_SINE; | ||
81 | effect->u.periodic.period = 50; | ||
82 | effect->u.periodic.magnitude = max(magnitude, 0x7fff); | ||
83 | effect->u.periodic.offset = 0; | ||
84 | effect->u.periodic.phase = 0; | ||
85 | effect->u.periodic.envelope.attack_length = 0; | ||
86 | effect->u.periodic.envelope.attack_level = 0; | ||
87 | effect->u.periodic.envelope.fade_length = 0; | ||
88 | effect->u.periodic.envelope.fade_level = 0; | ||
89 | |||
90 | return 0; | ||
91 | |||
92 | default: | ||
93 | /* Let driver handle conversion */ | ||
94 | return 0; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * input_ff_upload() - upload effect into force-feedback device | ||
100 | * @dev: input device | ||
101 | * @effect: effect to be uploaded | ||
102 | * @file: owner of the effect | ||
103 | */ | ||
104 | int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, | ||
105 | struct file *file) | ||
106 | { | ||
107 | struct ff_device *ff = dev->ff; | ||
108 | struct ff_effect *old; | ||
109 | int ret = 0; | ||
110 | int id; | ||
111 | |||
112 | if (!test_bit(EV_FF, dev->evbit)) | ||
113 | return -ENOSYS; | ||
114 | |||
115 | if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX || | ||
116 | !test_bit(effect->type, dev->ffbit)) { | ||
117 | debug("invalid or not supported effect type in upload"); | ||
118 | return -EINVAL; | ||
119 | } | ||
120 | |||
121 | if (effect->type == FF_PERIODIC && | ||
122 | (effect->u.periodic.waveform < FF_WAVEFORM_MIN || | ||
123 | effect->u.periodic.waveform > FF_WAVEFORM_MAX || | ||
124 | !test_bit(effect->u.periodic.waveform, dev->ffbit))) { | ||
125 | debug("invalid or not supported wave form in upload"); | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | if (!test_bit(effect->type, ff->ffbit)) { | ||
130 | ret = compat_effect(ff, effect); | ||
131 | if (ret) | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | mutex_lock(&ff->mutex); | ||
136 | |||
137 | if (effect->id == -1) { | ||
138 | for (id = 0; id < ff->max_effects; id++) | ||
139 | if (!ff->effect_owners[id]) | ||
140 | break; | ||
141 | |||
142 | if (id >= ff->max_effects) { | ||
143 | ret = -ENOSPC; | ||
144 | goto out; | ||
145 | } | ||
146 | |||
147 | effect->id = id; | ||
148 | old = NULL; | ||
149 | |||
150 | } else { | ||
151 | id = effect->id; | ||
152 | |||
153 | ret = check_effect_access(ff, id, file); | ||
154 | if (ret) | ||
155 | goto out; | ||
156 | |||
157 | old = &ff->effects[id]; | ||
158 | |||
159 | if (!check_effects_compatible(effect, old)) { | ||
160 | ret = -EINVAL; | ||
161 | goto out; | ||
162 | } | ||
163 | } | ||
164 | |||
165 | ret = ff->upload(dev, effect, old); | ||
166 | if (ret) | ||
167 | goto out; | ||
168 | |||
169 | ff->effects[id] = *effect; | ||
170 | ff->effect_owners[id] = file; | ||
171 | |||
172 | out: | ||
173 | mutex_unlock(&ff->mutex); | ||
174 | return ret; | ||
175 | } | ||
176 | EXPORT_SYMBOL_GPL(input_ff_upload); | ||
177 | |||
178 | /* | ||
179 | * Erases the effect if the requester is also the effect owner. The mutex | ||
180 | * should already be locked before calling this function. | ||
181 | */ | ||
182 | static int erase_effect(struct input_dev *dev, int effect_id, | ||
183 | struct file *file) | ||
184 | { | ||
185 | struct ff_device *ff = dev->ff; | ||
186 | int error; | ||
187 | |||
188 | error = check_effect_access(ff, effect_id, file); | ||
189 | if (error) | ||
190 | return error; | ||
191 | |||
192 | ff->playback(dev, effect_id, 0); | ||
193 | |||
194 | if (ff->erase) { | ||
195 | error = ff->erase(dev, effect_id); | ||
196 | if (error) | ||
197 | return error; | ||
198 | } | ||
199 | |||
200 | ff->effect_owners[effect_id] = NULL; | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * input_ff_erase - erase an effect from device | ||
207 | * @dev: input device to erase effect from | ||
208 | * @effect_id: id of the ffect to be erased | ||
209 | * @file: purported owner of the request | ||
210 | * | ||
211 | * This function erases a force-feedback effect from specified device. | ||
212 | * The effect will only be erased if it was uploaded through the same | ||
213 | * file handle that is requesting erase. | ||
214 | */ | ||
215 | int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file) | ||
216 | { | ||
217 | struct ff_device *ff = dev->ff; | ||
218 | int ret; | ||
219 | |||
220 | if (!test_bit(EV_FF, dev->evbit)) | ||
221 | return -ENOSYS; | ||
222 | |||
223 | mutex_lock(&ff->mutex); | ||
224 | ret = erase_effect(dev, effect_id, file); | ||
225 | mutex_unlock(&ff->mutex); | ||
226 | |||
227 | return ret; | ||
228 | } | ||
229 | EXPORT_SYMBOL_GPL(input_ff_erase); | ||
230 | |||
231 | /* | ||
232 | * flush_effects - erase all effects owned by a file handle | ||
233 | */ | ||
234 | static int flush_effects(struct input_dev *dev, struct file *file) | ||
235 | { | ||
236 | struct ff_device *ff = dev->ff; | ||
237 | int i; | ||
238 | |||
239 | debug("flushing now"); | ||
240 | |||
241 | mutex_lock(&ff->mutex); | ||
242 | |||
243 | for (i = 0; i < ff->max_effects; i++) | ||
244 | erase_effect(dev, i, file); | ||
245 | |||
246 | mutex_unlock(&ff->mutex); | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * input_ff_event() - generic handler for force-feedback events | ||
253 | * @dev: input device to send the effect to | ||
254 | * @type: event type (anything but EV_FF is ignored) | ||
255 | * @code: event code | ||
256 | * @value: event value | ||
257 | */ | ||
258 | int input_ff_event(struct input_dev *dev, unsigned int type, | ||
259 | unsigned int code, int value) | ||
260 | { | ||
261 | struct ff_device *ff = dev->ff; | ||
262 | |||
263 | if (type != EV_FF) | ||
264 | return 0; | ||
265 | |||
266 | mutex_lock(&ff->mutex); | ||
267 | |||
268 | switch (code) { | ||
269 | case FF_GAIN: | ||
270 | if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffff) | ||
271 | break; | ||
272 | |||
273 | ff->set_gain(dev, value); | ||
274 | break; | ||
275 | |||
276 | case FF_AUTOCENTER: | ||
277 | if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffff) | ||
278 | break; | ||
279 | |||
280 | ff->set_autocenter(dev, value); | ||
281 | break; | ||
282 | |||
283 | default: | ||
284 | ff->playback(dev, code, value); | ||
285 | break; | ||
286 | } | ||
287 | |||
288 | mutex_unlock(&ff->mutex); | ||
289 | return 0; | ||
290 | } | ||
291 | EXPORT_SYMBOL_GPL(input_ff_event); | ||
292 | |||
293 | /** | ||
294 | * input_ff_create() - create force-feedback device | ||
295 | * @dev: input device supporting force-feedback | ||
296 | * @max_effects: maximum number of effects supported by the device | ||
297 | * | ||
298 | * This function allocates all necessary memory for a force feedback | ||
299 | * portion of an input device and installs all default handlers. | ||
300 | * @dev->ffbit should be already set up before calling this function. | ||
301 | * Once ff device is created you need to setup its upload, erase, | ||
302 | * playback and other handlers before registering input device | ||
303 | */ | ||
304 | int input_ff_create(struct input_dev *dev, int max_effects) | ||
305 | { | ||
306 | struct ff_device *ff; | ||
307 | int i; | ||
308 | |||
309 | if (!max_effects) { | ||
310 | printk(KERN_ERR | ||
311 | "ff-core: cannot allocate device without any effects\n"); | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | ff = kzalloc(sizeof(struct ff_device) + | ||
316 | max_effects * sizeof(struct file *), GFP_KERNEL); | ||
317 | if (!ff) | ||
318 | return -ENOMEM; | ||
319 | |||
320 | ff->effects = kcalloc(max_effects, sizeof(struct ff_effect), | ||
321 | GFP_KERNEL); | ||
322 | if (!ff->effects) { | ||
323 | kfree(ff); | ||
324 | return -ENOMEM; | ||
325 | } | ||
326 | |||
327 | ff->max_effects = max_effects; | ||
328 | mutex_init(&ff->mutex); | ||
329 | |||
330 | dev->ff = ff; | ||
331 | dev->flush = flush_effects; | ||
332 | dev->event = input_ff_event; | ||
333 | set_bit(EV_FF, dev->evbit); | ||
334 | |||
335 | /* Copy "true" bits into ff device bitmap */ | ||
336 | for (i = 0; i <= FF_MAX; i++) | ||
337 | if (test_bit(i, dev->ffbit)) | ||
338 | set_bit(i, ff->ffbit); | ||
339 | |||
340 | /* we can emulate RUMBLE with periodic effects */ | ||
341 | if (test_bit(FF_PERIODIC, ff->ffbit)) | ||
342 | set_bit(FF_RUMBLE, dev->ffbit); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | EXPORT_SYMBOL_GPL(input_ff_create); | ||
347 | |||
348 | /** | ||
349 | * input_ff_free() - frees force feedback portion of input device | ||
350 | * @dev: input device supporintg force feedback | ||
351 | * | ||
352 | * This function is only needed in error path as input core will | ||
353 | * automatically free force feedback structures when device is | ||
354 | * destroyed. | ||
355 | */ | ||
356 | void input_ff_destroy(struct input_dev *dev) | ||
357 | { | ||
358 | clear_bit(EV_FF, dev->evbit); | ||
359 | if (dev->ff) { | ||
360 | if (dev->ff->destroy) | ||
361 | dev->ff->destroy(dev->ff); | ||
362 | kfree(dev->ff->private); | ||
363 | kfree(dev->ff); | ||
364 | dev->ff = NULL; | ||
365 | } | ||
366 | } | ||
367 | EXPORT_SYMBOL_GPL(input_ff_destroy); | ||
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c new file mode 100644 index 000000000000..cd8b7297e6df --- /dev/null +++ b/drivers/input/ff-memless.c | |||
@@ -0,0 +1,515 @@ | |||
1 | /* | ||
2 | * Force feedback support for memoryless devices | ||
3 | * | ||
4 | * Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
5 | * Copyright (c) 2006 Dmitry Torokhov <dtor@mail.ru> | ||
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 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | /* #define DEBUG */ | ||
25 | |||
26 | #define debug(format, arg...) pr_debug("ff-memless: " format "\n", ## arg) | ||
27 | |||
28 | #include <linux/input.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/mutex.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/sched.h> | ||
33 | |||
34 | #include "fixp-arith.h" | ||
35 | |||
36 | MODULE_LICENSE("GPL"); | ||
37 | MODULE_AUTHOR("Anssi Hannula <anssi.hannula@gmail.com>"); | ||
38 | MODULE_DESCRIPTION("Force feedback support for memoryless devices"); | ||
39 | |||
40 | /* Number of effects handled with memoryless devices */ | ||
41 | #define FF_MEMLESS_EFFECTS 16 | ||
42 | |||
43 | /* Envelope update interval in ms */ | ||
44 | #define FF_ENVELOPE_INTERVAL 50 | ||
45 | |||
46 | #define FF_EFFECT_STARTED 0 | ||
47 | #define FF_EFFECT_PLAYING 1 | ||
48 | #define FF_EFFECT_ABORTING 2 | ||
49 | |||
50 | struct ml_effect_state { | ||
51 | struct ff_effect *effect; | ||
52 | unsigned long flags; /* effect state (STARTED, PLAYING, etc) */ | ||
53 | int count; /* loop count of the effect */ | ||
54 | unsigned long play_at; /* start time */ | ||
55 | unsigned long stop_at; /* stop time */ | ||
56 | unsigned long adj_at; /* last time the effect was sent */ | ||
57 | }; | ||
58 | |||
59 | struct ml_device { | ||
60 | void *private; | ||
61 | struct ml_effect_state states[FF_MEMLESS_EFFECTS]; | ||
62 | int gain; | ||
63 | struct timer_list timer; | ||
64 | spinlock_t timer_lock; | ||
65 | struct input_dev *dev; | ||
66 | |||
67 | int (*play_effect)(struct input_dev *dev, void *data, | ||
68 | struct ff_effect *effect); | ||
69 | }; | ||
70 | |||
71 | static const struct ff_envelope *get_envelope(const struct ff_effect *effect) | ||
72 | { | ||
73 | static const struct ff_envelope empty_envelope; | ||
74 | |||
75 | switch (effect->type) { | ||
76 | case FF_PERIODIC: | ||
77 | return &effect->u.periodic.envelope; | ||
78 | case FF_CONSTANT: | ||
79 | return &effect->u.constant.envelope; | ||
80 | default: | ||
81 | return &empty_envelope; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * Check for the next time envelope requires an update on memoryless devices | ||
87 | */ | ||
88 | static unsigned long calculate_next_time(struct ml_effect_state *state) | ||
89 | { | ||
90 | const struct ff_envelope *envelope = get_envelope(state->effect); | ||
91 | unsigned long attack_stop, fade_start, next_fade; | ||
92 | |||
93 | if (envelope->attack_length) { | ||
94 | attack_stop = state->play_at + | ||
95 | msecs_to_jiffies(envelope->attack_length); | ||
96 | if (time_before(state->adj_at, attack_stop)) | ||
97 | return state->adj_at + | ||
98 | msecs_to_jiffies(FF_ENVELOPE_INTERVAL); | ||
99 | } | ||
100 | |||
101 | if (state->effect->replay.length) { | ||
102 | if (envelope->fade_length) { | ||
103 | /* check when fading should start */ | ||
104 | fade_start = state->stop_at - | ||
105 | msecs_to_jiffies(envelope->fade_length); | ||
106 | |||
107 | if (time_before(state->adj_at, fade_start)) | ||
108 | return fade_start; | ||
109 | |||
110 | /* already fading, advance to next checkpoint */ | ||
111 | next_fade = state->adj_at + | ||
112 | msecs_to_jiffies(FF_ENVELOPE_INTERVAL); | ||
113 | if (time_before(next_fade, state->stop_at)) | ||
114 | return next_fade; | ||
115 | } | ||
116 | |||
117 | return state->stop_at; | ||
118 | } | ||
119 | |||
120 | return state->play_at; | ||
121 | } | ||
122 | |||
123 | static void ml_schedule_timer(struct ml_device *ml) | ||
124 | { | ||
125 | struct ml_effect_state *state; | ||
126 | unsigned long now = jiffies; | ||
127 | unsigned long earliest = 0; | ||
128 | unsigned long next_at; | ||
129 | int events = 0; | ||
130 | int i; | ||
131 | |||
132 | debug("calculating next timer"); | ||
133 | |||
134 | for (i = 0; i < FF_MEMLESS_EFFECTS; i++) { | ||
135 | |||
136 | state = &ml->states[i]; | ||
137 | |||
138 | if (!test_bit(FF_EFFECT_STARTED, &state->flags)) | ||
139 | continue; | ||
140 | |||
141 | if (test_bit(FF_EFFECT_PLAYING, &state->flags)) | ||
142 | next_at = calculate_next_time(state); | ||
143 | else | ||
144 | next_at = state->play_at; | ||
145 | |||
146 | if (time_before_eq(now, next_at) && | ||
147 | (++events == 1 || time_before(next_at, earliest))) | ||
148 | earliest = next_at; | ||
149 | } | ||
150 | |||
151 | if (!events) { | ||
152 | debug("no actions"); | ||
153 | del_timer(&ml->timer); | ||
154 | } else { | ||
155 | debug("timer set"); | ||
156 | mod_timer(&ml->timer, earliest); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Apply an envelope to a value | ||
162 | */ | ||
163 | static int apply_envelope(struct ml_effect_state *state, int value, | ||
164 | struct ff_envelope *envelope) | ||
165 | { | ||
166 | struct ff_effect *effect = state->effect; | ||
167 | unsigned long now = jiffies; | ||
168 | int time_from_level; | ||
169 | int time_of_envelope; | ||
170 | int envelope_level; | ||
171 | int difference; | ||
172 | |||
173 | if (envelope->attack_length && | ||
174 | time_before(now, | ||
175 | state->play_at + msecs_to_jiffies(envelope->attack_length))) { | ||
176 | debug("value = 0x%x, attack_level = 0x%x", value, | ||
177 | envelope->attack_level); | ||
178 | time_from_level = jiffies_to_msecs(now - state->play_at); | ||
179 | time_of_envelope = envelope->attack_length; | ||
180 | envelope_level = min_t(__s16, envelope->attack_level, 0x7fff); | ||
181 | |||
182 | } else if (envelope->fade_length && effect->replay.length && | ||
183 | time_after(now, | ||
184 | state->stop_at - msecs_to_jiffies(envelope->fade_length)) && | ||
185 | time_before(now, state->stop_at)) { | ||
186 | time_from_level = jiffies_to_msecs(state->stop_at - now); | ||
187 | time_of_envelope = envelope->fade_length; | ||
188 | envelope_level = min_t(__s16, envelope->fade_level, 0x7fff); | ||
189 | } else | ||
190 | return value; | ||
191 | |||
192 | difference = abs(value) - envelope_level; | ||
193 | |||
194 | debug("difference = %d", difference); | ||
195 | debug("time_from_level = 0x%x", time_from_level); | ||
196 | debug("time_of_envelope = 0x%x", time_of_envelope); | ||
197 | |||
198 | difference = difference * time_from_level / time_of_envelope; | ||
199 | |||
200 | debug("difference = %d", difference); | ||
201 | |||
202 | return value < 0 ? | ||
203 | -(difference + envelope_level) : (difference + envelope_level); | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * Return the type the effect has to be converted into (memless devices) | ||
208 | */ | ||
209 | static int get_compatible_type(struct ff_device *ff, int effect_type) | ||
210 | { | ||
211 | |||
212 | if (test_bit(effect_type, ff->ffbit)) | ||
213 | return effect_type; | ||
214 | |||
215 | if (effect_type == FF_PERIODIC && test_bit(FF_RUMBLE, ff->ffbit)) | ||
216 | return FF_RUMBLE; | ||
217 | |||
218 | printk(KERN_ERR | ||
219 | "ff-memless: invalid type in get_compatible_type()\n"); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * Combine two effects and apply gain. | ||
226 | */ | ||
227 | static void ml_combine_effects(struct ff_effect *effect, | ||
228 | struct ml_effect_state *state, | ||
229 | int gain) | ||
230 | { | ||
231 | struct ff_effect *new = state->effect; | ||
232 | unsigned int strong, weak, i; | ||
233 | int x, y; | ||
234 | fixp_t level; | ||
235 | |||
236 | switch (new->type) { | ||
237 | case FF_CONSTANT: | ||
238 | i = new->direction * 360 / 0xffff; | ||
239 | level = fixp_new16(apply_envelope(state, | ||
240 | new->u.constant.level, | ||
241 | &new->u.constant.envelope)); | ||
242 | x = fixp_mult(fixp_sin(i), level) * gain / 0xffff; | ||
243 | y = fixp_mult(-fixp_cos(i), level) * gain / 0xffff; | ||
244 | /* | ||
245 | * here we abuse ff_ramp to hold x and y of constant force | ||
246 | * If in future any driver wants something else than x and y | ||
247 | * in s8, this should be changed to something more generic | ||
248 | */ | ||
249 | effect->u.ramp.start_level = | ||
250 | max(min(effect->u.ramp.start_level + x, 0x7f), -0x80); | ||
251 | effect->u.ramp.end_level = | ||
252 | max(min(effect->u.ramp.end_level + y, 0x7f), -0x80); | ||
253 | break; | ||
254 | |||
255 | case FF_RUMBLE: | ||
256 | strong = new->u.rumble.strong_magnitude * gain / 0xffff; | ||
257 | weak = new->u.rumble.weak_magnitude * gain / 0xffff; | ||
258 | effect->u.rumble.strong_magnitude = | ||
259 | min(strong + effect->u.rumble.strong_magnitude, | ||
260 | 0xffffU); | ||
261 | effect->u.rumble.weak_magnitude = | ||
262 | min(weak + effect->u.rumble.weak_magnitude, 0xffffU); | ||
263 | break; | ||
264 | |||
265 | case FF_PERIODIC: | ||
266 | i = apply_envelope(state, abs(new->u.periodic.magnitude), | ||
267 | &new->u.periodic.envelope); | ||
268 | |||
269 | /* here we also scale it 0x7fff => 0xffff */ | ||
270 | i = i * gain / 0x7fff; | ||
271 | |||
272 | effect->u.rumble.strong_magnitude = | ||
273 | min(i + effect->u.rumble.strong_magnitude, 0xffffU); | ||
274 | effect->u.rumble.weak_magnitude = | ||
275 | min(i + effect->u.rumble.weak_magnitude, 0xffffU); | ||
276 | break; | ||
277 | |||
278 | default: | ||
279 | printk(KERN_ERR "ff-memless: invalid type in ml_combine_effects()\n"); | ||
280 | break; | ||
281 | } | ||
282 | |||
283 | } | ||
284 | |||
285 | |||
286 | /* | ||
287 | * Because memoryless devices have only one effect per effect type active | ||
288 | * at one time we have to combine multiple effects into one | ||
289 | */ | ||
290 | static int ml_get_combo_effect(struct ml_device *ml, | ||
291 | unsigned long *effect_handled, | ||
292 | struct ff_effect *combo_effect) | ||
293 | { | ||
294 | struct ff_effect *effect; | ||
295 | struct ml_effect_state *state; | ||
296 | int effect_type; | ||
297 | int i; | ||
298 | |||
299 | memset(combo_effect, 0, sizeof(struct ff_effect)); | ||
300 | |||
301 | for (i = 0; i < FF_MEMLESS_EFFECTS; i++) { | ||
302 | if (__test_and_set_bit(i, effect_handled)) | ||
303 | continue; | ||
304 | |||
305 | state = &ml->states[i]; | ||
306 | effect = state->effect; | ||
307 | |||
308 | if (!test_bit(FF_EFFECT_STARTED, &state->flags)) | ||
309 | continue; | ||
310 | |||
311 | if (time_before(jiffies, state->play_at)) | ||
312 | continue; | ||
313 | |||
314 | /* | ||
315 | * here we have started effects that are either | ||
316 | * currently playing (and may need be aborted) | ||
317 | * or need to start playing. | ||
318 | */ | ||
319 | effect_type = get_compatible_type(ml->dev->ff, effect->type); | ||
320 | if (combo_effect->type != effect_type) { | ||
321 | if (combo_effect->type != 0) { | ||
322 | __clear_bit(i, effect_handled); | ||
323 | continue; | ||
324 | } | ||
325 | combo_effect->type = effect_type; | ||
326 | } | ||
327 | |||
328 | if (__test_and_clear_bit(FF_EFFECT_ABORTING, &state->flags)) { | ||
329 | __clear_bit(FF_EFFECT_PLAYING, &state->flags); | ||
330 | __clear_bit(FF_EFFECT_STARTED, &state->flags); | ||
331 | } else if (effect->replay.length && | ||
332 | time_after_eq(jiffies, state->stop_at)) { | ||
333 | |||
334 | __clear_bit(FF_EFFECT_PLAYING, &state->flags); | ||
335 | |||
336 | if (--state->count <= 0) { | ||
337 | __clear_bit(FF_EFFECT_STARTED, &state->flags); | ||
338 | } else { | ||
339 | state->play_at = jiffies + | ||
340 | msecs_to_jiffies(effect->replay.delay); | ||
341 | state->stop_at = state->play_at + | ||
342 | msecs_to_jiffies(effect->replay.length); | ||
343 | } | ||
344 | } else { | ||
345 | __set_bit(FF_EFFECT_PLAYING, &state->flags); | ||
346 | state->adj_at = jiffies; | ||
347 | ml_combine_effects(combo_effect, state, ml->gain); | ||
348 | } | ||
349 | } | ||
350 | |||
351 | return combo_effect->type != 0; | ||
352 | } | ||
353 | |||
354 | static void ml_play_effects(struct ml_device *ml) | ||
355 | { | ||
356 | struct ff_effect effect; | ||
357 | DECLARE_BITMAP(handled_bm, FF_MEMLESS_EFFECTS); | ||
358 | |||
359 | memset(handled_bm, 0, sizeof(handled_bm)); | ||
360 | |||
361 | while (ml_get_combo_effect(ml, handled_bm, &effect)) | ||
362 | ml->play_effect(ml->dev, ml->private, &effect); | ||
363 | |||
364 | ml_schedule_timer(ml); | ||
365 | } | ||
366 | |||
367 | static void ml_effect_timer(unsigned long timer_data) | ||
368 | { | ||
369 | struct input_dev *dev = (struct input_dev *)timer_data; | ||
370 | struct ml_device *ml = dev->ff->private; | ||
371 | |||
372 | debug("timer: updating effects"); | ||
373 | |||
374 | spin_lock(&ml->timer_lock); | ||
375 | ml_play_effects(ml); | ||
376 | spin_unlock(&ml->timer_lock); | ||
377 | } | ||
378 | |||
379 | static void ml_ff_set_gain(struct input_dev *dev, u16 gain) | ||
380 | { | ||
381 | struct ml_device *ml = dev->ff->private; | ||
382 | int i; | ||
383 | |||
384 | spin_lock_bh(&ml->timer_lock); | ||
385 | |||
386 | ml->gain = gain; | ||
387 | |||
388 | for (i = 0; i < FF_MEMLESS_EFFECTS; i++) | ||
389 | __clear_bit(FF_EFFECT_PLAYING, &ml->states[i].flags); | ||
390 | |||
391 | ml_play_effects(ml); | ||
392 | |||
393 | spin_unlock_bh(&ml->timer_lock); | ||
394 | } | ||
395 | |||
396 | static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) | ||
397 | { | ||
398 | struct ml_device *ml = dev->ff->private; | ||
399 | struct ml_effect_state *state = &ml->states[effect_id]; | ||
400 | |||
401 | spin_lock_bh(&ml->timer_lock); | ||
402 | |||
403 | if (value > 0) { | ||
404 | debug("initiated play"); | ||
405 | |||
406 | __set_bit(FF_EFFECT_STARTED, &state->flags); | ||
407 | state->count = value; | ||
408 | state->play_at = jiffies + | ||
409 | msecs_to_jiffies(state->effect->replay.delay); | ||
410 | state->stop_at = state->play_at + | ||
411 | msecs_to_jiffies(state->effect->replay.length); | ||
412 | state->adj_at = state->play_at; | ||
413 | |||
414 | ml_schedule_timer(ml); | ||
415 | |||
416 | } else { | ||
417 | debug("initiated stop"); | ||
418 | |||
419 | if (test_bit(FF_EFFECT_PLAYING, &state->flags)) | ||
420 | __set_bit(FF_EFFECT_ABORTING, &state->flags); | ||
421 | else | ||
422 | __clear_bit(FF_EFFECT_STARTED, &state->flags); | ||
423 | |||
424 | ml_play_effects(ml); | ||
425 | } | ||
426 | |||
427 | spin_unlock_bh(&ml->timer_lock); | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static int ml_ff_upload(struct input_dev *dev, | ||
433 | struct ff_effect *effect, struct ff_effect *old) | ||
434 | { | ||
435 | struct ml_device *ml = dev->ff->private; | ||
436 | struct ml_effect_state *state = &ml->states[effect->id]; | ||
437 | |||
438 | spin_lock_bh(&ml->timer_lock); | ||
439 | |||
440 | if (test_bit(FF_EFFECT_STARTED, &state->flags)) { | ||
441 | __clear_bit(FF_EFFECT_PLAYING, &state->flags); | ||
442 | state->play_at = jiffies + | ||
443 | msecs_to_jiffies(state->effect->replay.delay); | ||
444 | state->stop_at = state->play_at + | ||
445 | msecs_to_jiffies(state->effect->replay.length); | ||
446 | state->adj_at = state->play_at; | ||
447 | ml_schedule_timer(ml); | ||
448 | } | ||
449 | |||
450 | spin_unlock_bh(&ml->timer_lock); | ||
451 | |||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static void ml_ff_destroy(struct ff_device *ff) | ||
456 | { | ||
457 | struct ml_device *ml = ff->private; | ||
458 | |||
459 | kfree(ml->private); | ||
460 | } | ||
461 | |||
462 | /** | ||
463 | * input_ff_create_memless() - create memoryless FF device | ||
464 | * @dev: input device supporting force-feedback | ||
465 | * @data: driver-specific data to be passed into @play_effect | ||
466 | * @play_effect: driver-specific method for playing FF effect | ||
467 | */ | ||
468 | int input_ff_create_memless(struct input_dev *dev, void *data, | ||
469 | int (*play_effect)(struct input_dev *, void *, struct ff_effect *)) | ||
470 | { | ||
471 | struct ml_device *ml; | ||
472 | struct ff_device *ff; | ||
473 | int error; | ||
474 | int i; | ||
475 | |||
476 | ml = kzalloc(sizeof(struct ml_device), GFP_KERNEL); | ||
477 | if (!ml) | ||
478 | return -ENOMEM; | ||
479 | |||
480 | ml->dev = dev; | ||
481 | ml->private = data; | ||
482 | ml->play_effect = play_effect; | ||
483 | ml->gain = 0xffff; | ||
484 | spin_lock_init(&ml->timer_lock); | ||
485 | setup_timer(&ml->timer, ml_effect_timer, (unsigned long)dev); | ||
486 | |||
487 | set_bit(FF_GAIN, dev->ffbit); | ||
488 | |||
489 | error = input_ff_create(dev, FF_MEMLESS_EFFECTS); | ||
490 | if (error) { | ||
491 | kfree(ml); | ||
492 | return error; | ||
493 | } | ||
494 | |||
495 | ff = dev->ff; | ||
496 | ff->private = ml; | ||
497 | ff->upload = ml_ff_upload; | ||
498 | ff->playback = ml_ff_playback; | ||
499 | ff->set_gain = ml_ff_set_gain; | ||
500 | ff->destroy = ml_ff_destroy; | ||
501 | |||
502 | /* we can emulate periodic effects with RUMBLE */ | ||
503 | if (test_bit(FF_RUMBLE, ff->ffbit)) { | ||
504 | set_bit(FF_PERIODIC, dev->ffbit); | ||
505 | set_bit(FF_SINE, dev->ffbit); | ||
506 | set_bit(FF_TRIANGLE, dev->ffbit); | ||
507 | set_bit(FF_SQUARE, dev->ffbit); | ||
508 | } | ||
509 | |||
510 | for (i = 0; i < FF_MEMLESS_EFFECTS; i++) | ||
511 | ml->states[i].effect = &ff->effects[i]; | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | EXPORT_SYMBOL_GPL(input_ff_create_memless); | ||
diff --git a/drivers/usb/input/fixp-arith.h b/drivers/input/fixp-arith.h index ed3d2da0c485..ed3d2da0c485 100644 --- a/drivers/usb/input/fixp-arith.h +++ b/drivers/input/fixp-arith.h | |||
diff --git a/drivers/input/input.c b/drivers/input/input.c index 9cb4b9a54f01..1c8c8a5bc4a9 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -176,6 +176,10 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in | |||
176 | break; | 176 | break; |
177 | 177 | ||
178 | case EV_FF: | 178 | case EV_FF: |
179 | |||
180 | if (value < 0) | ||
181 | return; | ||
182 | |||
179 | if (dev->event) | 183 | if (dev->event) |
180 | dev->event(dev, type, code, value); | 184 | dev->event(dev, type, code, value); |
181 | break; | 185 | break; |
@@ -309,7 +313,8 @@ static void input_link_handle(struct input_handle *handle) | |||
309 | if (i != NBITS(max)) \ | 313 | if (i != NBITS(max)) \ |
310 | continue; | 314 | continue; |
311 | 315 | ||
312 | static struct input_device_id *input_match_device(struct input_device_id *id, struct input_dev *dev) | 316 | static const struct input_device_id *input_match_device(const struct input_device_id *id, |
317 | struct input_dev *dev) | ||
313 | { | 318 | { |
314 | int i; | 319 | int i; |
315 | 320 | ||
@@ -762,7 +767,9 @@ static void input_dev_release(struct class_device *class_dev) | |||
762 | { | 767 | { |
763 | struct input_dev *dev = to_input_dev(class_dev); | 768 | struct input_dev *dev = to_input_dev(class_dev); |
764 | 769 | ||
770 | input_ff_destroy(dev); | ||
765 | kfree(dev); | 771 | kfree(dev); |
772 | |||
766 | module_put(THIS_MODULE); | 773 | module_put(THIS_MODULE); |
767 | } | 774 | } |
768 | 775 | ||
@@ -899,12 +906,13 @@ struct input_dev *input_allocate_device(void) | |||
899 | 906 | ||
900 | dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); | 907 | dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); |
901 | if (dev) { | 908 | if (dev) { |
902 | dev->dynalloc = 1; | ||
903 | dev->cdev.class = &input_class; | 909 | dev->cdev.class = &input_class; |
904 | class_device_initialize(&dev->cdev); | 910 | class_device_initialize(&dev->cdev); |
905 | mutex_init(&dev->mutex); | 911 | mutex_init(&dev->mutex); |
906 | INIT_LIST_HEAD(&dev->h_list); | 912 | INIT_LIST_HEAD(&dev->h_list); |
907 | INIT_LIST_HEAD(&dev->node); | 913 | INIT_LIST_HEAD(&dev->node); |
914 | |||
915 | __module_get(THIS_MODULE); | ||
908 | } | 916 | } |
909 | 917 | ||
910 | return dev; | 918 | return dev; |
@@ -929,17 +937,10 @@ int input_register_device(struct input_dev *dev) | |||
929 | static atomic_t input_no = ATOMIC_INIT(0); | 937 | static atomic_t input_no = ATOMIC_INIT(0); |
930 | struct input_handle *handle; | 938 | struct input_handle *handle; |
931 | struct input_handler *handler; | 939 | struct input_handler *handler; |
932 | struct input_device_id *id; | 940 | const struct input_device_id *id; |
933 | const char *path; | 941 | const char *path; |
934 | int error; | 942 | int error; |
935 | 943 | ||
936 | if (!dev->dynalloc) { | ||
937 | printk(KERN_WARNING "input: device %s is statically allocated, will not register\n" | ||
938 | "Please convert to input_allocate_device() or contact dtor_core@ameritech.net\n", | ||
939 | dev->name ? dev->name : "<Unknown>"); | ||
940 | return -EINVAL; | ||
941 | } | ||
942 | |||
943 | set_bit(EV_SYN, dev->evbit); | 944 | set_bit(EV_SYN, dev->evbit); |
944 | 945 | ||
945 | /* | 946 | /* |
@@ -955,10 +956,8 @@ int input_register_device(struct input_dev *dev) | |||
955 | dev->rep[REP_PERIOD] = 33; | 956 | dev->rep[REP_PERIOD] = 33; |
956 | } | 957 | } |
957 | 958 | ||
958 | INIT_LIST_HEAD(&dev->h_list); | ||
959 | list_add_tail(&dev->node, &input_dev_list); | 959 | list_add_tail(&dev->node, &input_dev_list); |
960 | 960 | ||
961 | dev->cdev.class = &input_class; | ||
962 | snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id), | 961 | snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id), |
963 | "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); | 962 | "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); |
964 | 963 | ||
@@ -978,8 +977,6 @@ int input_register_device(struct input_dev *dev) | |||
978 | if (error) | 977 | if (error) |
979 | goto fail3; | 978 | goto fail3; |
980 | 979 | ||
981 | __module_get(THIS_MODULE); | ||
982 | |||
983 | path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); | 980 | path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); |
984 | printk(KERN_INFO "input: %s as %s\n", | 981 | printk(KERN_INFO "input: %s as %s\n", |
985 | dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); | 982 | dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); |
@@ -1008,9 +1005,12 @@ EXPORT_SYMBOL(input_register_device); | |||
1008 | void input_unregister_device(struct input_dev *dev) | 1005 | void input_unregister_device(struct input_dev *dev) |
1009 | { | 1006 | { |
1010 | struct list_head *node, *next; | 1007 | struct list_head *node, *next; |
1008 | int code; | ||
1011 | 1009 | ||
1012 | if (!dev) | 1010 | for (code = 0; code <= KEY_MAX; code++) |
1013 | return; | 1011 | if (test_bit(code, dev->key)) |
1012 | input_report_key(dev, code, 0); | ||
1013 | input_sync(dev); | ||
1014 | 1014 | ||
1015 | del_timer_sync(&dev->timer); | 1015 | del_timer_sync(&dev->timer); |
1016 | 1016 | ||
@@ -1037,19 +1037,20 @@ void input_unregister_device(struct input_dev *dev) | |||
1037 | } | 1037 | } |
1038 | EXPORT_SYMBOL(input_unregister_device); | 1038 | EXPORT_SYMBOL(input_unregister_device); |
1039 | 1039 | ||
1040 | void input_register_handler(struct input_handler *handler) | 1040 | int input_register_handler(struct input_handler *handler) |
1041 | { | 1041 | { |
1042 | struct input_dev *dev; | 1042 | struct input_dev *dev; |
1043 | struct input_handle *handle; | 1043 | struct input_handle *handle; |
1044 | struct input_device_id *id; | 1044 | const struct input_device_id *id; |
1045 | |||
1046 | if (!handler) | ||
1047 | return; | ||
1048 | 1045 | ||
1049 | INIT_LIST_HEAD(&handler->h_list); | 1046 | INIT_LIST_HEAD(&handler->h_list); |
1050 | 1047 | ||
1051 | if (handler->fops != NULL) | 1048 | if (handler->fops != NULL) { |
1049 | if (input_table[handler->minor >> 5]) | ||
1050 | return -EBUSY; | ||
1051 | |||
1052 | input_table[handler->minor >> 5] = handler; | 1052 | input_table[handler->minor >> 5] = handler; |
1053 | } | ||
1053 | 1054 | ||
1054 | list_add_tail(&handler->node, &input_handler_list); | 1055 | list_add_tail(&handler->node, &input_handler_list); |
1055 | 1056 | ||
@@ -1063,6 +1064,7 @@ void input_register_handler(struct input_handler *handler) | |||
1063 | } | 1064 | } |
1064 | 1065 | ||
1065 | input_wakeup_procfs_readers(); | 1066 | input_wakeup_procfs_readers(); |
1067 | return 0; | ||
1066 | } | 1068 | } |
1067 | EXPORT_SYMBOL(input_register_handler); | 1069 | EXPORT_SYMBOL(input_register_handler); |
1068 | 1070 | ||
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index d67157513bf7..9f3529ad3fda 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -451,7 +451,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
451 | } | 451 | } |
452 | } | 452 | } |
453 | 453 | ||
454 | static struct file_operations joydev_fops = { | 454 | static const struct file_operations joydev_fops = { |
455 | .owner = THIS_MODULE, | 455 | .owner = THIS_MODULE, |
456 | .read = joydev_read, | 456 | .read = joydev_read, |
457 | .write = joydev_write, | 457 | .write = joydev_write, |
@@ -465,7 +465,8 @@ static struct file_operations joydev_fops = { | |||
465 | .fasync = joydev_fasync, | 465 | .fasync = joydev_fasync, |
466 | }; | 466 | }; |
467 | 467 | ||
468 | static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id) | 468 | static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, |
469 | const struct input_device_id *id) | ||
469 | { | 470 | { |
470 | struct joydev *joydev; | 471 | struct joydev *joydev; |
471 | struct class_device *cdev; | 472 | struct class_device *cdev; |
@@ -562,7 +563,7 @@ static void joydev_disconnect(struct input_handle *handle) | |||
562 | joydev_free(joydev); | 563 | joydev_free(joydev); |
563 | } | 564 | } |
564 | 565 | ||
565 | static struct input_device_id joydev_blacklist[] = { | 566 | static const struct input_device_id joydev_blacklist[] = { |
566 | { | 567 | { |
567 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, | 568 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, |
568 | .evbit = { BIT(EV_KEY) }, | 569 | .evbit = { BIT(EV_KEY) }, |
@@ -571,7 +572,7 @@ static struct input_device_id joydev_blacklist[] = { | |||
571 | { } /* Terminating entry */ | 572 | { } /* Terminating entry */ |
572 | }; | 573 | }; |
573 | 574 | ||
574 | static struct input_device_id joydev_ids[] = { | 575 | static const struct input_device_id joydev_ids[] = { |
575 | { | 576 | { |
576 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | 577 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, |
577 | .evbit = { BIT(EV_ABS) }, | 578 | .evbit = { BIT(EV_ABS) }, |
@@ -605,8 +606,7 @@ static struct input_handler joydev_handler = { | |||
605 | 606 | ||
606 | static int __init joydev_init(void) | 607 | static int __init joydev_init(void) |
607 | { | 608 | { |
608 | input_register_handler(&joydev_handler); | 609 | return input_register_handler(&joydev_handler); |
609 | return 0; | ||
610 | } | 610 | } |
611 | 611 | ||
612 | static void __exit joydev_exit(void) | 612 | static void __exit joydev_exit(void) |
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c index 50c90765aee1..8fb0c19cc60e 100644 --- a/drivers/input/joystick/iforce/iforce-ff.c +++ b/drivers/input/joystick/iforce/iforce-ff.c | |||
@@ -165,19 +165,19 @@ static int make_condition_modifier(struct iforce* iforce, | |||
165 | data[0] = LO(mod_chunk->start); | 165 | data[0] = LO(mod_chunk->start); |
166 | data[1] = HI(mod_chunk->start); | 166 | data[1] = HI(mod_chunk->start); |
167 | 167 | ||
168 | data[2] = (100*rk)>>15; /* Dangerous: the sign is extended by gcc on plateforms providing an arith shift */ | 168 | data[2] = (100 * rk) >> 15; /* Dangerous: the sign is extended by gcc on plateforms providing an arith shift */ |
169 | data[3] = (100*lk)>>15; /* This code is incorrect on cpus lacking arith shift */ | 169 | data[3] = (100 * lk) >> 15; /* This code is incorrect on cpus lacking arith shift */ |
170 | 170 | ||
171 | center = (500*center)>>15; | 171 | center = (500 * center) >> 15; |
172 | data[4] = LO(center); | 172 | data[4] = LO(center); |
173 | data[5] = HI(center); | 173 | data[5] = HI(center); |
174 | 174 | ||
175 | db = (1000*db)>>16; | 175 | db = (1000 * db) >> 16; |
176 | data[6] = LO(db); | 176 | data[6] = LO(db); |
177 | data[7] = HI(db); | 177 | data[7] = HI(db); |
178 | 178 | ||
179 | data[8] = (100*rsat)>>16; | 179 | data[8] = (100 * rsat) >> 16; |
180 | data[9] = (100*lsat)>>16; | 180 | data[9] = (100 * lsat) >> 16; |
181 | 181 | ||
182 | iforce_send_packet(iforce, FF_CMD_CONDITION, data); | 182 | iforce_send_packet(iforce, FF_CMD_CONDITION, data); |
183 | iforce_dump_packet("condition", FF_CMD_CONDITION, data); | 183 | iforce_dump_packet("condition", FF_CMD_CONDITION, data); |
@@ -188,6 +188,7 @@ static int make_condition_modifier(struct iforce* iforce, | |||
188 | static unsigned char find_button(struct iforce *iforce, signed short button) | 188 | static unsigned char find_button(struct iforce *iforce, signed short button) |
189 | { | 189 | { |
190 | int i; | 190 | int i; |
191 | |||
191 | for (i = 1; iforce->type->btn[i] >= 0; i++) | 192 | for (i = 1; iforce->type->btn[i] >= 0; i++) |
192 | if (iforce->type->btn[i] == button) | 193 | if (iforce->type->btn[i] == button) |
193 | return i + 1; | 194 | return i + 1; |
@@ -198,19 +199,17 @@ static unsigned char find_button(struct iforce *iforce, signed short button) | |||
198 | * Analyse the changes in an effect, and tell if we need to send an condition | 199 | * Analyse the changes in an effect, and tell if we need to send an condition |
199 | * parameter packet | 200 | * parameter packet |
200 | */ | 201 | */ |
201 | static int need_condition_modifier(struct iforce* iforce, struct ff_effect* new) | 202 | static int need_condition_modifier(struct ff_effect *old, struct ff_effect *new) |
202 | { | 203 | { |
203 | int id = new->id; | 204 | int ret = 0; |
204 | struct ff_effect* old = &iforce->core_effects[id].effect; | ||
205 | int ret=0; | ||
206 | int i; | 205 | int i; |
207 | 206 | ||
208 | if (new->type != FF_SPRING && new->type != FF_FRICTION) { | 207 | if (new->type != FF_SPRING && new->type != FF_FRICTION) { |
209 | printk(KERN_WARNING "iforce.c: bad effect type in need_condition_modifier\n"); | 208 | printk(KERN_WARNING "iforce.c: bad effect type in need_condition_modifier\n"); |
210 | return FALSE; | 209 | return 0; |
211 | } | 210 | } |
212 | 211 | ||
213 | for(i=0; i<2; i++) { | 212 | for (i = 0; i < 2; i++) { |
214 | ret |= old->u.condition[i].right_saturation != new->u.condition[i].right_saturation | 213 | ret |= old->u.condition[i].right_saturation != new->u.condition[i].right_saturation |
215 | || old->u.condition[i].left_saturation != new->u.condition[i].left_saturation | 214 | || old->u.condition[i].left_saturation != new->u.condition[i].left_saturation |
216 | || old->u.condition[i].right_coeff != new->u.condition[i].right_coeff | 215 | || old->u.condition[i].right_coeff != new->u.condition[i].right_coeff |
@@ -225,35 +224,29 @@ static int need_condition_modifier(struct iforce* iforce, struct ff_effect* new) | |||
225 | * Analyse the changes in an effect, and tell if we need to send a magnitude | 224 | * Analyse the changes in an effect, and tell if we need to send a magnitude |
226 | * parameter packet | 225 | * parameter packet |
227 | */ | 226 | */ |
228 | static int need_magnitude_modifier(struct iforce* iforce, struct ff_effect* effect) | 227 | static int need_magnitude_modifier(struct ff_effect *old, struct ff_effect *effect) |
229 | { | 228 | { |
230 | int id = effect->id; | ||
231 | struct ff_effect* old = &iforce->core_effects[id].effect; | ||
232 | |||
233 | if (effect->type != FF_CONSTANT) { | 229 | if (effect->type != FF_CONSTANT) { |
234 | printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n"); | 230 | printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n"); |
235 | return FALSE; | 231 | return 0; |
236 | } | 232 | } |
237 | 233 | ||
238 | return (old->u.constant.level != effect->u.constant.level); | 234 | return old->u.constant.level != effect->u.constant.level; |
239 | } | 235 | } |
240 | 236 | ||
241 | /* | 237 | /* |
242 | * Analyse the changes in an effect, and tell if we need to send an envelope | 238 | * Analyse the changes in an effect, and tell if we need to send an envelope |
243 | * parameter packet | 239 | * parameter packet |
244 | */ | 240 | */ |
245 | static int need_envelope_modifier(struct iforce* iforce, struct ff_effect* effect) | 241 | static int need_envelope_modifier(struct ff_effect *old, struct ff_effect *effect) |
246 | { | 242 | { |
247 | int id = effect->id; | ||
248 | struct ff_effect* old = &iforce->core_effects[id].effect; | ||
249 | |||
250 | switch (effect->type) { | 243 | switch (effect->type) { |
251 | case FF_CONSTANT: | 244 | case FF_CONSTANT: |
252 | if (old->u.constant.envelope.attack_length != effect->u.constant.envelope.attack_length | 245 | if (old->u.constant.envelope.attack_length != effect->u.constant.envelope.attack_length |
253 | || old->u.constant.envelope.attack_level != effect->u.constant.envelope.attack_level | 246 | || old->u.constant.envelope.attack_level != effect->u.constant.envelope.attack_level |
254 | || old->u.constant.envelope.fade_length != effect->u.constant.envelope.fade_length | 247 | || old->u.constant.envelope.fade_length != effect->u.constant.envelope.fade_length |
255 | || old->u.constant.envelope.fade_level != effect->u.constant.envelope.fade_level) | 248 | || old->u.constant.envelope.fade_level != effect->u.constant.envelope.fade_level) |
256 | return TRUE; | 249 | return 1; |
257 | break; | 250 | break; |
258 | 251 | ||
259 | case FF_PERIODIC: | 252 | case FF_PERIODIC: |
@@ -261,30 +254,26 @@ static int need_envelope_modifier(struct iforce* iforce, struct ff_effect* effec | |||
261 | || old->u.periodic.envelope.attack_level != effect->u.periodic.envelope.attack_level | 254 | || old->u.periodic.envelope.attack_level != effect->u.periodic.envelope.attack_level |
262 | || old->u.periodic.envelope.fade_length != effect->u.periodic.envelope.fade_length | 255 | || old->u.periodic.envelope.fade_length != effect->u.periodic.envelope.fade_length |
263 | || old->u.periodic.envelope.fade_level != effect->u.periodic.envelope.fade_level) | 256 | || old->u.periodic.envelope.fade_level != effect->u.periodic.envelope.fade_level) |
264 | return TRUE; | 257 | return 1; |
265 | break; | 258 | break; |
266 | 259 | ||
267 | default: | 260 | default: |
268 | printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n"); | 261 | printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n"); |
269 | } | 262 | } |
270 | 263 | ||
271 | return FALSE; | 264 | return 0; |
272 | } | 265 | } |
273 | 266 | ||
274 | /* | 267 | /* |
275 | * Analyse the changes in an effect, and tell if we need to send a periodic | 268 | * Analyse the changes in an effect, and tell if we need to send a periodic |
276 | * parameter effect | 269 | * parameter effect |
277 | */ | 270 | */ |
278 | static int need_period_modifier(struct iforce* iforce, struct ff_effect* new) | 271 | static int need_period_modifier(struct ff_effect *old, struct ff_effect *new) |
279 | { | 272 | { |
280 | int id = new->id; | ||
281 | struct ff_effect* old = &iforce->core_effects[id].effect; | ||
282 | |||
283 | if (new->type != FF_PERIODIC) { | 273 | if (new->type != FF_PERIODIC) { |
284 | printk(KERN_WARNING "iforce.c: bad effect type in need_periodic_modifier\n"); | 274 | printk(KERN_WARNING "iforce.c: bad effect type in need_period_modifier\n"); |
285 | return FALSE; | 275 | return 0; |
286 | } | 276 | } |
287 | |||
288 | return (old->u.periodic.period != new->u.periodic.period | 277 | return (old->u.periodic.period != new->u.periodic.period |
289 | || old->u.periodic.magnitude != new->u.periodic.magnitude | 278 | || old->u.periodic.magnitude != new->u.periodic.magnitude |
290 | || old->u.periodic.offset != new->u.periodic.offset | 279 | || old->u.periodic.offset != new->u.periodic.offset |
@@ -295,19 +284,16 @@ static int need_period_modifier(struct iforce* iforce, struct ff_effect* new) | |||
295 | * Analyse the changes in an effect, and tell if we need to send an effect | 284 | * Analyse the changes in an effect, and tell if we need to send an effect |
296 | * packet | 285 | * packet |
297 | */ | 286 | */ |
298 | static int need_core(struct iforce* iforce, struct ff_effect* new) | 287 | static int need_core(struct ff_effect *old, struct ff_effect *new) |
299 | { | 288 | { |
300 | int id = new->id; | ||
301 | struct ff_effect* old = &iforce->core_effects[id].effect; | ||
302 | |||
303 | if (old->direction != new->direction | 289 | if (old->direction != new->direction |
304 | || old->trigger.button != new->trigger.button | 290 | || old->trigger.button != new->trigger.button |
305 | || old->trigger.interval != new->trigger.interval | 291 | || old->trigger.interval != new->trigger.interval |
306 | || old->replay.length != new->replay.length | 292 | || old->replay.length != new->replay.length |
307 | || old->replay.delay != new->replay.delay) | 293 | || old->replay.delay != new->replay.delay) |
308 | return TRUE; | 294 | return 1; |
309 | 295 | ||
310 | return FALSE; | 296 | return 0; |
311 | } | 297 | } |
312 | /* | 298 | /* |
313 | * Send the part common to all effects to the device | 299 | * Send the part common to all effects to the device |
@@ -360,7 +346,7 @@ static int make_core(struct iforce* iforce, u16 id, u16 mod_id1, u16 mod_id2, | |||
360 | * Upload a periodic effect to the device | 346 | * Upload a periodic effect to the device |
361 | * See also iforce_upload_constant. | 347 | * See also iforce_upload_constant. |
362 | */ | 348 | */ |
363 | int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect, int is_update) | 349 | int iforce_upload_periodic(struct iforce *iforce, struct ff_effect *effect, struct ff_effect *old) |
364 | { | 350 | { |
365 | u8 wave_code; | 351 | u8 wave_code; |
366 | int core_id = effect->id; | 352 | int core_id = effect->id; |
@@ -371,23 +357,25 @@ int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect, int | |||
371 | int param2_err = 1; | 357 | int param2_err = 1; |
372 | int core_err = 0; | 358 | int core_err = 0; |
373 | 359 | ||
374 | if (!is_update || need_period_modifier(iforce, effect)) { | 360 | if (!old || need_period_modifier(old, effect)) { |
375 | param1_err = make_period_modifier(iforce, mod1_chunk, | 361 | param1_err = make_period_modifier(iforce, mod1_chunk, |
376 | is_update, | 362 | old != NULL, |
377 | effect->u.periodic.magnitude, effect->u.periodic.offset, | 363 | effect->u.periodic.magnitude, effect->u.periodic.offset, |
378 | effect->u.periodic.period, effect->u.periodic.phase); | 364 | effect->u.periodic.period, effect->u.periodic.phase); |
379 | if (param1_err) return param1_err; | 365 | if (param1_err) |
366 | return param1_err; | ||
380 | set_bit(FF_MOD1_IS_USED, core_effect->flags); | 367 | set_bit(FF_MOD1_IS_USED, core_effect->flags); |
381 | } | 368 | } |
382 | 369 | ||
383 | if (!is_update || need_envelope_modifier(iforce, effect)) { | 370 | if (!old || need_envelope_modifier(old, effect)) { |
384 | param2_err = make_envelope_modifier(iforce, mod2_chunk, | 371 | param2_err = make_envelope_modifier(iforce, mod2_chunk, |
385 | is_update, | 372 | old !=NULL, |
386 | effect->u.periodic.envelope.attack_length, | 373 | effect->u.periodic.envelope.attack_length, |
387 | effect->u.periodic.envelope.attack_level, | 374 | effect->u.periodic.envelope.attack_level, |
388 | effect->u.periodic.envelope.fade_length, | 375 | effect->u.periodic.envelope.fade_length, |
389 | effect->u.periodic.envelope.fade_level); | 376 | effect->u.periodic.envelope.fade_level); |
390 | if (param2_err) return param2_err; | 377 | if (param2_err) |
378 | return param2_err; | ||
391 | set_bit(FF_MOD2_IS_USED, core_effect->flags); | 379 | set_bit(FF_MOD2_IS_USED, core_effect->flags); |
392 | } | 380 | } |
393 | 381 | ||
@@ -400,7 +388,7 @@ int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect, int | |||
400 | default: wave_code = 0x20; break; | 388 | default: wave_code = 0x20; break; |
401 | } | 389 | } |
402 | 390 | ||
403 | if (!is_update || need_core(iforce, effect)) { | 391 | if (!old || need_core(old, effect)) { |
404 | core_err = make_core(iforce, effect->id, | 392 | core_err = make_core(iforce, effect->id, |
405 | mod1_chunk->start, | 393 | mod1_chunk->start, |
406 | mod2_chunk->start, | 394 | mod2_chunk->start, |
@@ -429,7 +417,7 @@ int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect, int | |||
429 | * 0 Ok, effect created or updated | 417 | * 0 Ok, effect created or updated |
430 | * 1 effect did not change since last upload, and no packet was therefore sent | 418 | * 1 effect did not change since last upload, and no packet was therefore sent |
431 | */ | 419 | */ |
432 | int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect, int is_update) | 420 | int iforce_upload_constant(struct iforce *iforce, struct ff_effect *effect, struct ff_effect *old) |
433 | { | 421 | { |
434 | int core_id = effect->id; | 422 | int core_id = effect->id; |
435 | struct iforce_core_effect* core_effect = iforce->core_effects + core_id; | 423 | struct iforce_core_effect* core_effect = iforce->core_effects + core_id; |
@@ -439,26 +427,28 @@ int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect, int | |||
439 | int param2_err = 1; | 427 | int param2_err = 1; |
440 | int core_err = 0; | 428 | int core_err = 0; |
441 | 429 | ||
442 | if (!is_update || need_magnitude_modifier(iforce, effect)) { | 430 | if (!old || need_magnitude_modifier(old, effect)) { |
443 | param1_err = make_magnitude_modifier(iforce, mod1_chunk, | 431 | param1_err = make_magnitude_modifier(iforce, mod1_chunk, |
444 | is_update, | 432 | old != NULL, |
445 | effect->u.constant.level); | 433 | effect->u.constant.level); |
446 | if (param1_err) return param1_err; | 434 | if (param1_err) |
435 | return param1_err; | ||
447 | set_bit(FF_MOD1_IS_USED, core_effect->flags); | 436 | set_bit(FF_MOD1_IS_USED, core_effect->flags); |
448 | } | 437 | } |
449 | 438 | ||
450 | if (!is_update || need_envelope_modifier(iforce, effect)) { | 439 | if (!old || need_envelope_modifier(old, effect)) { |
451 | param2_err = make_envelope_modifier(iforce, mod2_chunk, | 440 | param2_err = make_envelope_modifier(iforce, mod2_chunk, |
452 | is_update, | 441 | old != NULL, |
453 | effect->u.constant.envelope.attack_length, | 442 | effect->u.constant.envelope.attack_length, |
454 | effect->u.constant.envelope.attack_level, | 443 | effect->u.constant.envelope.attack_level, |
455 | effect->u.constant.envelope.fade_length, | 444 | effect->u.constant.envelope.fade_length, |
456 | effect->u.constant.envelope.fade_level); | 445 | effect->u.constant.envelope.fade_level); |
457 | if (param2_err) return param2_err; | 446 | if (param2_err) |
447 | return param2_err; | ||
458 | set_bit(FF_MOD2_IS_USED, core_effect->flags); | 448 | set_bit(FF_MOD2_IS_USED, core_effect->flags); |
459 | } | 449 | } |
460 | 450 | ||
461 | if (!is_update || need_core(iforce, effect)) { | 451 | if (!old || need_core(old, effect)) { |
462 | core_err = make_core(iforce, effect->id, | 452 | core_err = make_core(iforce, effect->id, |
463 | mod1_chunk->start, | 453 | mod1_chunk->start, |
464 | mod2_chunk->start, | 454 | mod2_chunk->start, |
@@ -483,7 +473,7 @@ int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect, int | |||
483 | /* | 473 | /* |
484 | * Upload an condition effect. Those are for example friction, inertia, springs... | 474 | * Upload an condition effect. Those are for example friction, inertia, springs... |
485 | */ | 475 | */ |
486 | int iforce_upload_condition(struct iforce* iforce, struct ff_effect* effect, int is_update) | 476 | int iforce_upload_condition(struct iforce *iforce, struct ff_effect *effect, struct ff_effect *old) |
487 | { | 477 | { |
488 | int core_id = effect->id; | 478 | int core_id = effect->id; |
489 | struct iforce_core_effect* core_effect = iforce->core_effects + core_id; | 479 | struct iforce_core_effect* core_effect = iforce->core_effects + core_id; |
@@ -494,37 +484,39 @@ int iforce_upload_condition(struct iforce* iforce, struct ff_effect* effect, int | |||
494 | int core_err = 0; | 484 | int core_err = 0; |
495 | 485 | ||
496 | switch (effect->type) { | 486 | switch (effect->type) { |
497 | case FF_SPRING: type = 0x40; break; | 487 | case FF_SPRING: type = 0x40; break; |
498 | case FF_DAMPER: type = 0x41; break; | 488 | case FF_DAMPER: type = 0x41; break; |
499 | default: return -1; | 489 | default: return -1; |
500 | } | 490 | } |
501 | 491 | ||
502 | if (!is_update || need_condition_modifier(iforce, effect)) { | 492 | if (!old || need_condition_modifier(old, effect)) { |
503 | param_err = make_condition_modifier(iforce, mod1_chunk, | 493 | param_err = make_condition_modifier(iforce, mod1_chunk, |
504 | is_update, | 494 | old != NULL, |
505 | effect->u.condition[0].right_saturation, | 495 | effect->u.condition[0].right_saturation, |
506 | effect->u.condition[0].left_saturation, | 496 | effect->u.condition[0].left_saturation, |
507 | effect->u.condition[0].right_coeff, | 497 | effect->u.condition[0].right_coeff, |
508 | effect->u.condition[0].left_coeff, | 498 | effect->u.condition[0].left_coeff, |
509 | effect->u.condition[0].deadband, | 499 | effect->u.condition[0].deadband, |
510 | effect->u.condition[0].center); | 500 | effect->u.condition[0].center); |
511 | if (param_err) return param_err; | 501 | if (param_err) |
502 | return param_err; | ||
512 | set_bit(FF_MOD1_IS_USED, core_effect->flags); | 503 | set_bit(FF_MOD1_IS_USED, core_effect->flags); |
513 | 504 | ||
514 | param_err = make_condition_modifier(iforce, mod2_chunk, | 505 | param_err = make_condition_modifier(iforce, mod2_chunk, |
515 | is_update, | 506 | old != NULL, |
516 | effect->u.condition[1].right_saturation, | 507 | effect->u.condition[1].right_saturation, |
517 | effect->u.condition[1].left_saturation, | 508 | effect->u.condition[1].left_saturation, |
518 | effect->u.condition[1].right_coeff, | 509 | effect->u.condition[1].right_coeff, |
519 | effect->u.condition[1].left_coeff, | 510 | effect->u.condition[1].left_coeff, |
520 | effect->u.condition[1].deadband, | 511 | effect->u.condition[1].deadband, |
521 | effect->u.condition[1].center); | 512 | effect->u.condition[1].center); |
522 | if (param_err) return param_err; | 513 | if (param_err) |
514 | return param_err; | ||
523 | set_bit(FF_MOD2_IS_USED, core_effect->flags); | 515 | set_bit(FF_MOD2_IS_USED, core_effect->flags); |
524 | 516 | ||
525 | } | 517 | } |
526 | 518 | ||
527 | if (!is_update || need_core(iforce, effect)) { | 519 | if (!old || need_core(old, effect)) { |
528 | core_err = make_core(iforce, effect->id, | 520 | core_err = make_core(iforce, effect->id, |
529 | mod1_chunk->start, mod2_chunk->start, | 521 | mod1_chunk->start, mod2_chunk->start, |
530 | type, 0xc0, | 522 | type, 0xc0, |
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index b4914e7231f8..24c684bc6337 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c | |||
@@ -83,103 +83,57 @@ static struct iforce_device iforce_device[] = { | |||
83 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } | 83 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } |
84 | }; | 84 | }; |
85 | 85 | ||
86 | 86 | static int iforce_playback(struct input_dev *dev, int effect_id, int value) | |
87 | |||
88 | static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | ||
89 | { | 87 | { |
90 | struct iforce* iforce = dev->private; | 88 | struct iforce* iforce = dev->private; |
91 | unsigned char data[3]; | 89 | struct iforce_core_effect *core_effect = &iforce->core_effects[effect_id]; |
92 | |||
93 | if (type != EV_FF) | ||
94 | return -1; | ||
95 | |||
96 | switch (code) { | ||
97 | |||
98 | case FF_GAIN: | ||
99 | |||
100 | data[0] = value >> 9; | ||
101 | iforce_send_packet(iforce, FF_CMD_GAIN, data); | ||
102 | |||
103 | return 0; | ||
104 | |||
105 | case FF_AUTOCENTER: | ||
106 | 90 | ||
107 | data[0] = 0x03; | 91 | if (value > 0) |
108 | data[1] = value >> 9; | 92 | set_bit(FF_CORE_SHOULD_PLAY, core_effect->flags); |
109 | iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data); | 93 | else |
94 | clear_bit(FF_CORE_SHOULD_PLAY, core_effect->flags); | ||
110 | 95 | ||
111 | data[0] = 0x04; | 96 | iforce_control_playback(iforce, effect_id, value); |
112 | data[1] = 0x01; | 97 | return 0; |
113 | iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data); | 98 | } |
114 | 99 | ||
115 | return 0; | 100 | static void iforce_set_gain(struct input_dev *dev, u16 gain) |
101 | { | ||
102 | struct iforce* iforce = dev->private; | ||
103 | unsigned char data[3]; | ||
116 | 104 | ||
117 | default: /* Play or stop an effect */ | 105 | data[0] = gain >> 9; |
106 | iforce_send_packet(iforce, FF_CMD_GAIN, data); | ||
107 | } | ||
118 | 108 | ||
119 | if (!CHECK_OWNERSHIP(code, iforce)) { | 109 | static void iforce_set_autocenter(struct input_dev *dev, u16 magnitude) |
120 | return -1; | 110 | { |
121 | } | 111 | struct iforce* iforce = dev->private; |
122 | if (value > 0) { | 112 | unsigned char data[3]; |
123 | set_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags); | ||
124 | } | ||
125 | else { | ||
126 | clear_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags); | ||
127 | } | ||
128 | 113 | ||
129 | iforce_control_playback(iforce, code, value); | 114 | data[0] = 0x03; |
130 | return 0; | 115 | data[1] = magnitude >> 9; |
131 | } | 116 | iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data); |
132 | 117 | ||
133 | return -1; | 118 | data[0] = 0x04; |
119 | data[1] = 0x01; | ||
120 | iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data); | ||
134 | } | 121 | } |
135 | 122 | ||
136 | /* | 123 | /* |
137 | * Function called when an ioctl is performed on the event dev entry. | 124 | * Function called when an ioctl is performed on the event dev entry. |
138 | * It uploads an effect to the device | 125 | * It uploads an effect to the device |
139 | */ | 126 | */ |
140 | static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect) | 127 | static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) |
141 | { | 128 | { |
142 | struct iforce* iforce = dev->private; | 129 | struct iforce* iforce = dev->private; |
143 | int id; | 130 | struct iforce_core_effect *core_effect = &iforce->core_effects[effect->id]; |
144 | int ret; | 131 | int ret; |
145 | int is_update; | ||
146 | |||
147 | /* Check this effect type is supported by this device */ | ||
148 | if (!test_bit(effect->type, iforce->dev->ffbit)) | ||
149 | return -EINVAL; | ||
150 | |||
151 | /* | ||
152 | * If we want to create a new effect, get a free id | ||
153 | */ | ||
154 | if (effect->id == -1) { | ||
155 | |||
156 | for (id = 0; id < FF_EFFECTS_MAX; ++id) | ||
157 | if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) | ||
158 | break; | ||
159 | |||
160 | if (id == FF_EFFECTS_MAX || id >= iforce->dev->ff_effects_max) | ||
161 | return -ENOMEM; | ||
162 | |||
163 | effect->id = id; | ||
164 | iforce->core_effects[id].owner = current->pid; | ||
165 | iforce->core_effects[id].flags[0] = (1 << FF_CORE_IS_USED); /* Only IS_USED bit must be set */ | ||
166 | |||
167 | is_update = FALSE; | ||
168 | } | ||
169 | else { | ||
170 | /* We want to update an effect */ | ||
171 | if (!CHECK_OWNERSHIP(effect->id, iforce)) | ||
172 | return -EACCES; | ||
173 | |||
174 | /* Parameter type cannot be updated */ | ||
175 | if (effect->type != iforce->core_effects[effect->id].effect.type) | ||
176 | return -EINVAL; | ||
177 | 132 | ||
133 | if (__test_and_set_bit(FF_CORE_IS_USED, core_effect->flags)) { | ||
178 | /* Check the effect is not already being updated */ | 134 | /* Check the effect is not already being updated */ |
179 | if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags)) | 135 | if (test_bit(FF_CORE_UPDATE, core_effect->flags)) |
180 | return -EAGAIN; | 136 | return -EAGAIN; |
181 | |||
182 | is_update = TRUE; | ||
183 | } | 137 | } |
184 | 138 | ||
185 | /* | 139 | /* |
@@ -188,28 +142,28 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect) | |||
188 | switch (effect->type) { | 142 | switch (effect->type) { |
189 | 143 | ||
190 | case FF_PERIODIC: | 144 | case FF_PERIODIC: |
191 | ret = iforce_upload_periodic(iforce, effect, is_update); | 145 | ret = iforce_upload_periodic(iforce, effect, old); |
192 | break; | 146 | break; |
193 | 147 | ||
194 | case FF_CONSTANT: | 148 | case FF_CONSTANT: |
195 | ret = iforce_upload_constant(iforce, effect, is_update); | 149 | ret = iforce_upload_constant(iforce, effect, old); |
196 | break; | 150 | break; |
197 | 151 | ||
198 | case FF_SPRING: | 152 | case FF_SPRING: |
199 | case FF_DAMPER: | 153 | case FF_DAMPER: |
200 | ret = iforce_upload_condition(iforce, effect, is_update); | 154 | ret = iforce_upload_condition(iforce, effect, old); |
201 | break; | 155 | break; |
202 | 156 | ||
203 | default: | 157 | default: |
204 | return -EINVAL; | 158 | return -EINVAL; |
205 | } | 159 | } |
160 | |||
206 | if (ret == 0) { | 161 | if (ret == 0) { |
207 | /* A packet was sent, forbid new updates until we are notified | 162 | /* A packet was sent, forbid new updates until we are notified |
208 | * that the packet was updated | 163 | * that the packet was updated |
209 | */ | 164 | */ |
210 | set_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags); | 165 | set_bit(FF_CORE_UPDATE, core_effect->flags); |
211 | } | 166 | } |
212 | iforce->core_effects[effect->id].effect = *effect; | ||
213 | return ret; | 167 | return ret; |
214 | } | 168 | } |
215 | 169 | ||
@@ -219,20 +173,9 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect) | |||
219 | */ | 173 | */ |
220 | static int iforce_erase_effect(struct input_dev *dev, int effect_id) | 174 | static int iforce_erase_effect(struct input_dev *dev, int effect_id) |
221 | { | 175 | { |
222 | struct iforce* iforce = dev->private; | 176 | struct iforce *iforce = dev->private; |
177 | struct iforce_core_effect *core_effect = &iforce->core_effects[effect_id]; | ||
223 | int err = 0; | 178 | int err = 0; |
224 | struct iforce_core_effect* core_effect; | ||
225 | |||
226 | if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX) | ||
227 | return -EINVAL; | ||
228 | |||
229 | core_effect = &iforce->core_effects[effect_id]; | ||
230 | |||
231 | /* Check who is trying to erase this effect */ | ||
232 | if (core_effect->owner != current->pid) { | ||
233 | printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, core_effect->owner); | ||
234 | return -EACCES; | ||
235 | } | ||
236 | 179 | ||
237 | if (test_bit(FF_MOD1_IS_USED, core_effect->flags)) | 180 | if (test_bit(FF_MOD1_IS_USED, core_effect->flags)) |
238 | err = release_resource(&core_effect->mod1_chunk); | 181 | err = release_resource(&core_effect->mod1_chunk); |
@@ -240,7 +183,7 @@ static int iforce_erase_effect(struct input_dev *dev, int effect_id) | |||
240 | if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags)) | 183 | if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags)) |
241 | err = release_resource(&core_effect->mod2_chunk); | 184 | err = release_resource(&core_effect->mod2_chunk); |
242 | 185 | ||
243 | /*TODO: remember to change that if more FF_MOD* bits are added */ | 186 | /* TODO: remember to change that if more FF_MOD* bits are added */ |
244 | core_effect->flags[0] = 0; | 187 | core_effect->flags[0] = 0; |
245 | 188 | ||
246 | return err; | 189 | return err; |
@@ -260,52 +203,31 @@ static int iforce_open(struct input_dev *dev) | |||
260 | #endif | 203 | #endif |
261 | } | 204 | } |
262 | 205 | ||
263 | /* Enable force feedback */ | 206 | if (test_bit(EV_FF, dev->evbit)) { |
264 | iforce_send_packet(iforce, FF_CMD_ENABLE, "\004"); | 207 | /* Enable force feedback */ |
208 | iforce_send_packet(iforce, FF_CMD_ENABLE, "\004"); | ||
209 | } | ||
265 | 210 | ||
266 | return 0; | 211 | return 0; |
267 | } | 212 | } |
268 | 213 | ||
269 | static int iforce_flush(struct input_dev *dev, struct file *file) | 214 | static void iforce_release(struct input_dev *dev) |
270 | { | 215 | { |
271 | struct iforce *iforce = dev->private; | 216 | struct iforce *iforce = dev->private; |
272 | int i; | 217 | int i; |
273 | 218 | ||
274 | /* Erase all effects this process owns */ | 219 | if (test_bit(EV_FF, dev->evbit)) { |
275 | for (i=0; i<dev->ff_effects_max; ++i) { | 220 | /* Check: no effects should be present in memory */ |
276 | 221 | for (i = 0; i < dev->ff->max_effects; i++) { | |
277 | if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) && | 222 | if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags)) { |
278 | current->pid == iforce->core_effects[i].owner) { | 223 | printk(KERN_WARNING "iforce_release: Device still owns effects\n"); |
279 | 224 | break; | |
280 | /* Stop effect */ | ||
281 | input_report_ff(dev, i, 0); | ||
282 | |||
283 | /* Free ressources assigned to effect */ | ||
284 | if (iforce_erase_effect(dev, i)) { | ||
285 | printk(KERN_WARNING "iforce_flush: erase effect %d failed\n", i); | ||
286 | } | 225 | } |
287 | } | 226 | } |
288 | 227 | ||
228 | /* Disable force feedback playback */ | ||
229 | iforce_send_packet(iforce, FF_CMD_ENABLE, "\001"); | ||
289 | } | 230 | } |
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static void iforce_release(struct input_dev *dev) | ||
294 | { | ||
295 | struct iforce *iforce = dev->private; | ||
296 | int i; | ||
297 | |||
298 | /* Check: no effect should be present in memory */ | ||
299 | for (i=0; i<dev->ff_effects_max; ++i) { | ||
300 | if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags)) | ||
301 | break; | ||
302 | } | ||
303 | if (i<dev->ff_effects_max) { | ||
304 | printk(KERN_WARNING "iforce_release: Device still owns effects\n"); | ||
305 | } | ||
306 | |||
307 | /* Disable force feedback playback */ | ||
308 | iforce_send_packet(iforce, FF_CMD_ENABLE, "\001"); | ||
309 | 231 | ||
310 | switch (iforce->bus) { | 232 | switch (iforce->bus) { |
311 | #ifdef CONFIG_JOYSTICK_IFORCE_USB | 233 | #ifdef CONFIG_JOYSTICK_IFORCE_USB |
@@ -342,8 +264,10 @@ void iforce_delete_device(struct iforce *iforce) | |||
342 | int iforce_init_device(struct iforce *iforce) | 264 | int iforce_init_device(struct iforce *iforce) |
343 | { | 265 | { |
344 | struct input_dev *input_dev; | 266 | struct input_dev *input_dev; |
267 | struct ff_device *ff; | ||
345 | unsigned char c[] = "CEOV"; | 268 | unsigned char c[] = "CEOV"; |
346 | int i; | 269 | int i, error; |
270 | int ff_effects = 0; | ||
347 | 271 | ||
348 | input_dev = input_allocate_device(); | 272 | input_dev = input_allocate_device(); |
349 | if (!input_dev) | 273 | if (!input_dev) |
@@ -378,11 +302,6 @@ int iforce_init_device(struct iforce *iforce) | |||
378 | input_dev->name = "Unknown I-Force device"; | 302 | input_dev->name = "Unknown I-Force device"; |
379 | input_dev->open = iforce_open; | 303 | input_dev->open = iforce_open; |
380 | input_dev->close = iforce_release; | 304 | input_dev->close = iforce_release; |
381 | input_dev->flush = iforce_flush; | ||
382 | input_dev->event = iforce_input_event; | ||
383 | input_dev->upload_effect = iforce_upload_effect; | ||
384 | input_dev->erase_effect = iforce_erase_effect; | ||
385 | input_dev->ff_effects_max = 10; | ||
386 | 305 | ||
387 | /* | 306 | /* |
388 | * On-device memory allocation. | 307 | * On-device memory allocation. |
@@ -430,15 +349,15 @@ int iforce_init_device(struct iforce *iforce) | |||
430 | printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n"); | 349 | printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n"); |
431 | 350 | ||
432 | if (!iforce_get_id_packet(iforce, "N")) | 351 | if (!iforce_get_id_packet(iforce, "N")) |
433 | iforce->dev->ff_effects_max = iforce->edata[1]; | 352 | ff_effects = iforce->edata[1]; |
434 | else | 353 | else |
435 | printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n"); | 354 | printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n"); |
436 | 355 | ||
437 | /* Check if the device can store more effects than the driver can really handle */ | 356 | /* Check if the device can store more effects than the driver can really handle */ |
438 | if (iforce->dev->ff_effects_max > FF_EFFECTS_MAX) { | 357 | if (ff_effects > IFORCE_EFFECTS_MAX) { |
439 | printk(KERN_WARNING "input??: Device can handle %d effects, but N_EFFECTS_MAX is set to %d in iforce.h\n", | 358 | printk(KERN_WARNING "iforce: Limiting number of effects to %d (device reports %d)\n", |
440 | iforce->dev->ff_effects_max, FF_EFFECTS_MAX); | 359 | IFORCE_EFFECTS_MAX, ff_effects); |
441 | iforce->dev->ff_effects_max = FF_EFFECTS_MAX; | 360 | ff_effects = IFORCE_EFFECTS_MAX; |
442 | } | 361 | } |
443 | 362 | ||
444 | /* | 363 | /* |
@@ -472,12 +391,10 @@ int iforce_init_device(struct iforce *iforce) | |||
472 | * Set input device bitfields and ranges. | 391 | * Set input device bitfields and ranges. |
473 | */ | 392 | */ |
474 | 393 | ||
475 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS); | 394 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF_STATUS); |
476 | 395 | ||
477 | for (i = 0; iforce->type->btn[i] >= 0; i++) { | 396 | for (i = 0; iforce->type->btn[i] >= 0; i++) |
478 | signed short t = iforce->type->btn[i]; | 397 | set_bit(iforce->type->btn[i], input_dev->keybit); |
479 | set_bit(t, input_dev->keybit); | ||
480 | } | ||
481 | set_bit(BTN_DEAD, input_dev->keybit); | 398 | set_bit(BTN_DEAD, input_dev->keybit); |
482 | 399 | ||
483 | for (i = 0; iforce->type->abs[i] >= 0; i++) { | 400 | for (i = 0; iforce->type->abs[i] >= 0; i++) { |
@@ -516,9 +433,24 @@ int iforce_init_device(struct iforce *iforce) | |||
516 | } | 433 | } |
517 | } | 434 | } |
518 | 435 | ||
519 | for (i = 0; iforce->type->ff[i] >= 0; i++) | 436 | if (ff_effects) { |
520 | set_bit(iforce->type->ff[i], input_dev->ffbit); | ||
521 | 437 | ||
438 | for (i = 0; iforce->type->ff[i] >= 0; i++) | ||
439 | set_bit(iforce->type->ff[i], input_dev->ffbit); | ||
440 | |||
441 | error = input_ff_create(input_dev, ff_effects); | ||
442 | if (error) { | ||
443 | input_free_device(input_dev); | ||
444 | return error; | ||
445 | } | ||
446 | |||
447 | ff = input_dev->ff; | ||
448 | ff->upload = iforce_upload_effect; | ||
449 | ff->erase = iforce_erase_effect; | ||
450 | ff->set_gain = iforce_set_gain; | ||
451 | ff->set_autocenter = iforce_set_autocenter; | ||
452 | ff->playback = iforce_playback; | ||
453 | } | ||
522 | /* | 454 | /* |
523 | * Register input device. | 455 | * Register input device. |
524 | */ | 456 | */ |
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index 76cb1f88f4e8..8632d47a7fbe 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c | |||
@@ -140,7 +140,10 @@ static int mark_core_as_ready(struct iforce *iforce, unsigned short addr) | |||
140 | { | 140 | { |
141 | int i; | 141 | int i; |
142 | 142 | ||
143 | for (i = 0; i < iforce->dev->ff_effects_max; ++i) { | 143 | if (!iforce->dev->ff) |
144 | return 0; | ||
145 | |||
146 | for (i = 0; i < iforce->dev->ff->max_effects; ++i) { | ||
144 | if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) && | 147 | if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) && |
145 | (iforce->core_effects[i].mod1_chunk.start == addr || | 148 | (iforce->core_effects[i].mod1_chunk.start == addr || |
146 | iforce->core_effects[i].mod2_chunk.start == addr)) { | 149 | iforce->core_effects[i].mod2_chunk.start == addr)) { |
@@ -229,19 +232,17 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, | |||
229 | i = data[1] & 0x7f; | 232 | i = data[1] & 0x7f; |
230 | if (data[1] & 0x80) { | 233 | if (data[1] & 0x80) { |
231 | if (!test_and_set_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) { | 234 | if (!test_and_set_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) { |
232 | /* Report play event */ | 235 | /* Report play event */ |
233 | input_report_ff_status(dev, i, FF_STATUS_PLAYING); | 236 | input_report_ff_status(dev, i, FF_STATUS_PLAYING); |
234 | } | 237 | } |
235 | } | 238 | } else if (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) { |
236 | else if (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) { | ||
237 | /* Report stop event */ | 239 | /* Report stop event */ |
238 | input_report_ff_status(dev, i, FF_STATUS_STOPPED); | 240 | input_report_ff_status(dev, i, FF_STATUS_STOPPED); |
239 | } | 241 | } |
240 | if (LO(cmd) > 3) { | 242 | if (LO(cmd) > 3) { |
241 | int j; | 243 | int j; |
242 | for (j=3; j<LO(cmd); j+=2) { | 244 | for (j = 3; j < LO(cmd); j += 2) |
243 | mark_core_as_ready(iforce, data[j] | (data[j+1]<<8)); | 245 | mark_core_as_ready(iforce, data[j] | (data[j+1]<<8)); |
244 | } | ||
245 | } | 246 | } |
246 | break; | 247 | break; |
247 | } | 248 | } |
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index e9924d6f01b3..947df2739843 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h | |||
@@ -51,10 +51,7 @@ | |||
51 | #define IFORCE_232 1 | 51 | #define IFORCE_232 1 |
52 | #define IFORCE_USB 2 | 52 | #define IFORCE_USB 2 |
53 | 53 | ||
54 | #define FALSE 0 | 54 | #define IFORCE_EFFECTS_MAX 32 |
55 | #define TRUE 1 | ||
56 | |||
57 | #define FF_EFFECTS_MAX 32 | ||
58 | 55 | ||
59 | /* Each force feedback effect is made of one core effect, which can be | 56 | /* Each force feedback effect is made of one core effect, which can be |
60 | * associated to at most to effect modifiers | 57 | * associated to at most to effect modifiers |
@@ -67,24 +64,11 @@ | |||
67 | #define FF_CORE_UPDATE 5 /* Effect is being updated */ | 64 | #define FF_CORE_UPDATE 5 /* Effect is being updated */ |
68 | #define FF_MODCORE_MAX 5 | 65 | #define FF_MODCORE_MAX 5 |
69 | 66 | ||
70 | #define CHECK_OWNERSHIP(i, iforce) \ | ||
71 | ((i) < FF_EFFECTS_MAX && i >= 0 && \ | ||
72 | test_bit(FF_CORE_IS_USED, (iforce)->core_effects[(i)].flags) && \ | ||
73 | (current->pid == 0 || \ | ||
74 | (iforce)->core_effects[(i)].owner == current->pid)) | ||
75 | |||
76 | struct iforce_core_effect { | 67 | struct iforce_core_effect { |
77 | /* Information about where modifiers are stored in the device's memory */ | 68 | /* Information about where modifiers are stored in the device's memory */ |
78 | struct resource mod1_chunk; | 69 | struct resource mod1_chunk; |
79 | struct resource mod2_chunk; | 70 | struct resource mod2_chunk; |
80 | unsigned long flags[NBITS(FF_MODCORE_MAX)]; | 71 | unsigned long flags[NBITS(FF_MODCORE_MAX)]; |
81 | pid_t owner; | ||
82 | /* Used to keep track of parameters of an effect. They are needed | ||
83 | * to know what parts of an effect changed in an update operation. | ||
84 | * We try to send only parameter packets if possible, as sending | ||
85 | * effect parameter requires the effect to be stoped and restarted | ||
86 | */ | ||
87 | struct ff_effect effect; | ||
88 | }; | 72 | }; |
89 | 73 | ||
90 | #define FF_CMD_EFFECT 0x010e | 74 | #define FF_CMD_EFFECT 0x010e |
@@ -145,7 +129,7 @@ struct iforce { | |||
145 | /* Force Feedback */ | 129 | /* Force Feedback */ |
146 | wait_queue_head_t wait; | 130 | wait_queue_head_t wait; |
147 | struct resource device_memory; | 131 | struct resource device_memory; |
148 | struct iforce_core_effect core_effects[FF_EFFECTS_MAX]; | 132 | struct iforce_core_effect core_effects[IFORCE_EFFECTS_MAX]; |
149 | struct mutex mem_mutex; | 133 | struct mutex mem_mutex; |
150 | }; | 134 | }; |
151 | 135 | ||
@@ -182,9 +166,9 @@ void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data) ; | |||
182 | int iforce_get_id_packet(struct iforce *iforce, char *packet); | 166 | int iforce_get_id_packet(struct iforce *iforce, char *packet); |
183 | 167 | ||
184 | /* iforce-ff.c */ | 168 | /* iforce-ff.c */ |
185 | int iforce_upload_periodic(struct iforce*, struct ff_effect*, int is_update); | 169 | int iforce_upload_periodic(struct iforce *, struct ff_effect *, struct ff_effect *); |
186 | int iforce_upload_constant(struct iforce*, struct ff_effect*, int is_update); | 170 | int iforce_upload_constant(struct iforce *, struct ff_effect *, struct ff_effect *); |
187 | int iforce_upload_condition(struct iforce*, struct ff_effect*, int is_update); | 171 | int iforce_upload_condition(struct iforce *, struct ff_effect *, struct ff_effect *); |
188 | 172 | ||
189 | /* Public variables */ | 173 | /* Public variables */ |
190 | extern struct serio_driver iforce_serio_drv; | 174 | extern struct serio_driver iforce_serio_drv; |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 83eac3a66bc8..c62e00c79dec 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -121,6 +121,17 @@ config KEYBOARD_NEWTON | |||
121 | To compile this driver as a module, choose M here: the | 121 | To compile this driver as a module, choose M here: the |
122 | module will be called newtonkbd. | 122 | module will be called newtonkbd. |
123 | 123 | ||
124 | config KEYBOARD_STOWAWAY | ||
125 | tristate "Stowaway keyboard" | ||
126 | select SERIO | ||
127 | help | ||
128 | Say Y here if you have a Stowaway keyboard on a serial port. | ||
129 | Stowaway compatible keyboards like Dicota Input-PDA keyboard | ||
130 | are also supported by this driver. | ||
131 | |||
132 | To compile this driver as a module, choose M here: the | ||
133 | module will be called stowaway. | ||
134 | |||
124 | config KEYBOARD_CORGI | 135 | config KEYBOARD_CORGI |
125 | tristate "Corgi keyboard" | 136 | tristate "Corgi keyboard" |
126 | depends on PXA_SHARPSL | 137 | depends on PXA_SHARPSL |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index b265391f1f10..4c79e7bc9d06 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | |||
11 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 11 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
12 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o | 12 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o |
13 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | 13 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o |
14 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | ||
14 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o | 15 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o |
15 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | 16 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o |
16 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 17 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index a86afd0a5ef1..40244d4ce0f1 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -652,9 +652,7 @@ static int atkbd_probe(struct atkbd *atkbd) | |||
652 | return 0; | 652 | return 0; |
653 | } | 653 | } |
654 | 654 | ||
655 | if (param[0] != 0xab && param[0] != 0xac && /* Regular and NCD Sun keyboards */ | 655 | if (!ps2_is_keyboard_id(param[0])) |
656 | param[0] != 0x2b && param[0] != 0x5d && /* Trust keyboard, raw and translated */ | ||
657 | param[0] != 0x60 && param[0] != 0x47) /* NMB SGI keyboard, raw and translated */ | ||
658 | return -1; | 656 | return -1; |
659 | 657 | ||
660 | atkbd->id = (param[0] << 8) | param[1]; | 658 | atkbd->id = (param[0] << 8) | param[1]; |
diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c new file mode 100644 index 000000000000..04c54c57f25c --- /dev/null +++ b/drivers/input/keyboard/stowaway.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * Stowaway keyboard driver for Linux | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | * Copyright (c) 2006 Marek Vasut | ||
7 | * | ||
8 | * Based on Newton keyboard driver for Linux | ||
9 | * by Justin Cormack | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
26 | * | ||
27 | * Should you need to contact me, the author, you can do so either by | ||
28 | * e-mail - mail your message to <marek.vasut@gmail.com>, or by paper mail: | ||
29 | * Marek Vasut, Liskovecka 559, Frydek-Mistek, 738 01 Czech Republic | ||
30 | */ | ||
31 | |||
32 | #include <linux/slab.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/input.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/serio.h> | ||
37 | |||
38 | #define DRIVER_DESC "Stowaway keyboard driver" | ||
39 | |||
40 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
41 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
42 | MODULE_LICENSE("GPL"); | ||
43 | |||
44 | #define SKBD_KEY_MASK 0x7f | ||
45 | #define SKBD_RELEASE 0x80 | ||
46 | |||
47 | static unsigned char skbd_keycode[128] = { | ||
48 | KEY_1, KEY_2, KEY_3, KEY_Z, KEY_4, KEY_5, KEY_6, KEY_7, | ||
49 | 0, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_GRAVE, | ||
50 | KEY_X, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_SPACE, | ||
51 | KEY_CAPSLOCK, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, | ||
52 | 0, 0, 0, KEY_LEFTALT, 0, 0, 0, 0, | ||
53 | 0, 0, 0, 0, KEY_C, KEY_V, KEY_B, KEY_N, | ||
54 | KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_HOME, KEY_8, KEY_9, KEY_0, KEY_ESC, | ||
55 | KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_END, KEY_U, KEY_I, KEY_O, KEY_P, | ||
56 | KEY_APOSTROPHE, KEY_ENTER, KEY_PAGEUP,0, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, | ||
57 | KEY_SLASH, KEY_UP, KEY_PAGEDOWN, 0,KEY_M, KEY_COMMA, KEY_DOT, KEY_INSERT, | ||
58 | KEY_DELETE, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, | ||
59 | KEY_LEFTSHIFT, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, | ||
60 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
61 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
62 | 0, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, | ||
63 | KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, 0, 0, 0 | ||
64 | }; | ||
65 | |||
66 | struct skbd { | ||
67 | unsigned char keycode[128]; | ||
68 | struct input_dev *dev; | ||
69 | struct serio *serio; | ||
70 | char phys[32]; | ||
71 | }; | ||
72 | |||
73 | static irqreturn_t skbd_interrupt(struct serio *serio, unsigned char data, | ||
74 | unsigned int flags, struct pt_regs *regs) | ||
75 | { | ||
76 | struct skbd *skbd = serio_get_drvdata(serio); | ||
77 | struct input_dev *dev = skbd->dev; | ||
78 | |||
79 | if (skbd->keycode[data & SKBD_KEY_MASK]) { | ||
80 | input_regs(dev, regs); | ||
81 | input_report_key(dev, skbd->keycode[data & SKBD_KEY_MASK], | ||
82 | !(data & SKBD_RELEASE)); | ||
83 | input_sync(dev); | ||
84 | } | ||
85 | |||
86 | return IRQ_HANDLED; | ||
87 | } | ||
88 | |||
89 | static int skbd_connect(struct serio *serio, struct serio_driver *drv) | ||
90 | { | ||
91 | struct skbd *skbd; | ||
92 | struct input_dev *input_dev; | ||
93 | int err = -ENOMEM; | ||
94 | int i; | ||
95 | |||
96 | skbd = kzalloc(sizeof(struct skbd), GFP_KERNEL); | ||
97 | input_dev = input_allocate_device(); | ||
98 | if (!skbd || !input_dev) | ||
99 | goto fail1; | ||
100 | |||
101 | skbd->serio = serio; | ||
102 | skbd->dev = input_dev; | ||
103 | snprintf(skbd->phys, sizeof(skbd->phys), "%s/input0", serio->phys); | ||
104 | memcpy(skbd->keycode, skbd_keycode, sizeof(skbd->keycode)); | ||
105 | |||
106 | input_dev->name = "Stowaway Keyboard"; | ||
107 | input_dev->phys = skbd->phys; | ||
108 | input_dev->id.bustype = BUS_RS232; | ||
109 | input_dev->id.vendor = SERIO_STOWAWAY; | ||
110 | input_dev->id.product = 0x0001; | ||
111 | input_dev->id.version = 0x0100; | ||
112 | input_dev->cdev.dev = &serio->dev; | ||
113 | input_dev->private = skbd; | ||
114 | |||
115 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
116 | input_dev->keycode = skbd->keycode; | ||
117 | input_dev->keycodesize = sizeof(unsigned char); | ||
118 | input_dev->keycodemax = ARRAY_SIZE(skbd_keycode); | ||
119 | for (i = 0; i < ARRAY_SIZE(skbd_keycode); i++) | ||
120 | set_bit(skbd_keycode[i], input_dev->keybit); | ||
121 | clear_bit(0, input_dev->keybit); | ||
122 | |||
123 | serio_set_drvdata(serio, skbd); | ||
124 | |||
125 | err = serio_open(serio, drv); | ||
126 | if (err) | ||
127 | goto fail2; | ||
128 | |||
129 | err = input_register_device(skbd->dev); | ||
130 | if (err) | ||
131 | goto fail3; | ||
132 | |||
133 | return 0; | ||
134 | |||
135 | fail3: serio_close(serio); | ||
136 | fail2: serio_set_drvdata(serio, NULL); | ||
137 | fail1: input_free_device(input_dev); | ||
138 | kfree(skbd); | ||
139 | return err; | ||
140 | } | ||
141 | |||
142 | static void skbd_disconnect(struct serio *serio) | ||
143 | { | ||
144 | struct skbd *skbd = serio_get_drvdata(serio); | ||
145 | |||
146 | serio_close(serio); | ||
147 | serio_set_drvdata(serio, NULL); | ||
148 | input_unregister_device(skbd->dev); | ||
149 | kfree(skbd); | ||
150 | } | ||
151 | |||
152 | static struct serio_device_id skbd_serio_ids[] = { | ||
153 | { | ||
154 | .type = SERIO_RS232, | ||
155 | .proto = SERIO_STOWAWAY, | ||
156 | .id = SERIO_ANY, | ||
157 | .extra = SERIO_ANY, | ||
158 | }, | ||
159 | { 0 } | ||
160 | }; | ||
161 | |||
162 | MODULE_DEVICE_TABLE(serio, skbd_serio_ids); | ||
163 | |||
164 | static struct serio_driver skbd_drv = { | ||
165 | .driver = { | ||
166 | .name = "stowaway", | ||
167 | }, | ||
168 | .description = DRIVER_DESC, | ||
169 | .id_table = skbd_serio_ids, | ||
170 | .interrupt = skbd_interrupt, | ||
171 | .connect = skbd_connect, | ||
172 | .disconnect = skbd_disconnect, | ||
173 | }; | ||
174 | |||
175 | static int __init skbd_init(void) | ||
176 | { | ||
177 | serio_register_driver(&skbd_drv); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static void __exit skbd_exit(void) | ||
182 | { | ||
183 | serio_unregister_driver(&skbd_drv); | ||
184 | } | ||
185 | |||
186 | module_init(skbd_init); | ||
187 | module_exit(skbd_exit); | ||
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index d723e9ad7c41..9516439b7c78 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
@@ -20,6 +20,9 @@ | |||
20 | * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> | 20 | * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> |
21 | * | 21 | * |
22 | * Changes/Revisions: | 22 | * Changes/Revisions: |
23 | * 0.3 09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>) | ||
24 | * - updated ff support for the changes in kernel interface | ||
25 | * - added MODULE_VERSION | ||
23 | * 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>) | 26 | * 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>) |
24 | * - added force feedback support | 27 | * - added force feedback support |
25 | * - added UI_SET_PHYS | 28 | * - added UI_SET_PHYS |
@@ -107,18 +110,31 @@ static int uinput_request_submit(struct input_dev *dev, struct uinput_request *r | |||
107 | return request->retval; | 110 | return request->retval; |
108 | } | 111 | } |
109 | 112 | ||
110 | static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect) | 113 | static void uinput_dev_set_gain(struct input_dev *dev, u16 gain) |
114 | { | ||
115 | uinput_dev_event(dev, EV_FF, FF_GAIN, gain); | ||
116 | } | ||
117 | |||
118 | static void uinput_dev_set_autocenter(struct input_dev *dev, u16 magnitude) | ||
119 | { | ||
120 | uinput_dev_event(dev, EV_FF, FF_AUTOCENTER, magnitude); | ||
121 | } | ||
122 | |||
123 | static int uinput_dev_playback(struct input_dev *dev, int effect_id, int value) | ||
124 | { | ||
125 | return uinput_dev_event(dev, EV_FF, effect_id, value); | ||
126 | } | ||
127 | |||
128 | static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) | ||
111 | { | 129 | { |
112 | struct uinput_request request; | 130 | struct uinput_request request; |
113 | int retval; | 131 | int retval; |
114 | 132 | ||
115 | if (!test_bit(EV_FF, dev->evbit)) | ||
116 | return -ENOSYS; | ||
117 | |||
118 | request.id = -1; | 133 | request.id = -1; |
119 | init_completion(&request.done); | 134 | init_completion(&request.done); |
120 | request.code = UI_FF_UPLOAD; | 135 | request.code = UI_FF_UPLOAD; |
121 | request.u.effect = effect; | 136 | request.u.upload.effect = effect; |
137 | request.u.upload.old = old; | ||
122 | 138 | ||
123 | retval = uinput_request_reserve_slot(dev->private, &request); | 139 | retval = uinput_request_reserve_slot(dev->private, &request); |
124 | if (!retval) | 140 | if (!retval) |
@@ -168,6 +184,7 @@ static void uinput_destroy_device(struct uinput_device *udev) | |||
168 | 184 | ||
169 | static int uinput_create_device(struct uinput_device *udev) | 185 | static int uinput_create_device(struct uinput_device *udev) |
170 | { | 186 | { |
187 | struct input_dev *dev = udev->dev; | ||
171 | int error; | 188 | int error; |
172 | 189 | ||
173 | if (udev->state != UIST_SETUP_COMPLETE) { | 190 | if (udev->state != UIST_SETUP_COMPLETE) { |
@@ -175,15 +192,29 @@ static int uinput_create_device(struct uinput_device *udev) | |||
175 | return -EINVAL; | 192 | return -EINVAL; |
176 | } | 193 | } |
177 | 194 | ||
178 | error = input_register_device(udev->dev); | 195 | if (udev->ff_effects_max) { |
179 | if (error) { | 196 | error = input_ff_create(dev, udev->ff_effects_max); |
180 | uinput_destroy_device(udev); | 197 | if (error) |
181 | return error; | 198 | goto fail1; |
199 | |||
200 | dev->ff->upload = uinput_dev_upload_effect; | ||
201 | dev->ff->erase = uinput_dev_erase_effect; | ||
202 | dev->ff->playback = uinput_dev_playback; | ||
203 | dev->ff->set_gain = uinput_dev_set_gain; | ||
204 | dev->ff->set_autocenter = uinput_dev_set_autocenter; | ||
182 | } | 205 | } |
183 | 206 | ||
207 | error = input_register_device(udev->dev); | ||
208 | if (error) | ||
209 | goto fail2; | ||
210 | |||
184 | udev->state = UIST_CREATED; | 211 | udev->state = UIST_CREATED; |
185 | 212 | ||
186 | return 0; | 213 | return 0; |
214 | |||
215 | fail2: input_ff_destroy(dev); | ||
216 | fail1: uinput_destroy_device(udev); | ||
217 | return error; | ||
187 | } | 218 | } |
188 | 219 | ||
189 | static int uinput_open(struct inode *inode, struct file *file) | 220 | static int uinput_open(struct inode *inode, struct file *file) |
@@ -243,8 +274,6 @@ static int uinput_allocate_device(struct uinput_device *udev) | |||
243 | return -ENOMEM; | 274 | return -ENOMEM; |
244 | 275 | ||
245 | udev->dev->event = uinput_dev_event; | 276 | udev->dev->event = uinput_dev_event; |
246 | udev->dev->upload_effect = uinput_dev_upload_effect; | ||
247 | udev->dev->erase_effect = uinput_dev_erase_effect; | ||
248 | udev->dev->private = udev; | 277 | udev->dev->private = udev; |
249 | 278 | ||
250 | return 0; | 279 | return 0; |
@@ -278,6 +307,8 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu | |||
278 | goto exit; | 307 | goto exit; |
279 | } | 308 | } |
280 | 309 | ||
310 | udev->ff_effects_max = user_dev->ff_effects_max; | ||
311 | |||
281 | size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1; | 312 | size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1; |
282 | if (!size) { | 313 | if (!size) { |
283 | retval = -EINVAL; | 314 | retval = -EINVAL; |
@@ -296,7 +327,6 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu | |||
296 | dev->id.vendor = user_dev->id.vendor; | 327 | dev->id.vendor = user_dev->id.vendor; |
297 | dev->id.product = user_dev->id.product; | 328 | dev->id.product = user_dev->id.product; |
298 | dev->id.version = user_dev->id.version; | 329 | dev->id.version = user_dev->id.version; |
299 | dev->ff_effects_max = user_dev->ff_effects_max; | ||
300 | 330 | ||
301 | size = sizeof(int) * (ABS_MAX + 1); | 331 | size = sizeof(int) * (ABS_MAX + 1); |
302 | memcpy(dev->absmax, user_dev->absmax, size); | 332 | memcpy(dev->absmax, user_dev->absmax, size); |
@@ -525,12 +555,17 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
525 | break; | 555 | break; |
526 | } | 556 | } |
527 | req = uinput_request_find(udev, ff_up.request_id); | 557 | req = uinput_request_find(udev, ff_up.request_id); |
528 | if (!(req && req->code == UI_FF_UPLOAD && req->u.effect)) { | 558 | if (!(req && req->code == UI_FF_UPLOAD && req->u.upload.effect)) { |
529 | retval = -EINVAL; | 559 | retval = -EINVAL; |
530 | break; | 560 | break; |
531 | } | 561 | } |
532 | ff_up.retval = 0; | 562 | ff_up.retval = 0; |
533 | memcpy(&ff_up.effect, req->u.effect, sizeof(struct ff_effect)); | 563 | memcpy(&ff_up.effect, req->u.upload.effect, sizeof(struct ff_effect)); |
564 | if (req->u.upload.old) | ||
565 | memcpy(&ff_up.old, req->u.upload.old, sizeof(struct ff_effect)); | ||
566 | else | ||
567 | memset(&ff_up.old, 0, sizeof(struct ff_effect)); | ||
568 | |||
534 | if (copy_to_user(p, &ff_up, sizeof(ff_up))) { | 569 | if (copy_to_user(p, &ff_up, sizeof(ff_up))) { |
535 | retval = -EFAULT; | 570 | retval = -EFAULT; |
536 | break; | 571 | break; |
@@ -561,12 +596,11 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
561 | break; | 596 | break; |
562 | } | 597 | } |
563 | req = uinput_request_find(udev, ff_up.request_id); | 598 | req = uinput_request_find(udev, ff_up.request_id); |
564 | if (!(req && req->code == UI_FF_UPLOAD && req->u.effect)) { | 599 | if (!(req && req->code == UI_FF_UPLOAD && req->u.upload.effect)) { |
565 | retval = -EINVAL; | 600 | retval = -EINVAL; |
566 | break; | 601 | break; |
567 | } | 602 | } |
568 | req->retval = ff_up.retval; | 603 | req->retval = ff_up.retval; |
569 | memcpy(req->u.effect, &ff_up.effect, sizeof(struct ff_effect)); | ||
570 | uinput_request_done(udev, req); | 604 | uinput_request_done(udev, req); |
571 | break; | 605 | break; |
572 | 606 | ||
@@ -622,6 +656,7 @@ static void __exit uinput_exit(void) | |||
622 | MODULE_AUTHOR("Aristeu Sergio Rozanski Filho"); | 656 | MODULE_AUTHOR("Aristeu Sergio Rozanski Filho"); |
623 | MODULE_DESCRIPTION("User level driver support for input subsystem"); | 657 | MODULE_DESCRIPTION("User level driver support for input subsystem"); |
624 | MODULE_LICENSE("GPL"); | 658 | MODULE_LICENSE("GPL"); |
659 | MODULE_VERSION("0.3"); | ||
625 | 660 | ||
626 | module_init(uinput_init); | 661 | module_init(uinput_init); |
627 | module_exit(uinput_exit); | 662 | module_exit(uinput_exit); |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index de0f46dd9692..4639537336fc 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -248,13 +248,10 @@ static int __init dmi_matched(struct dmi_system_id *dmi) | |||
248 | 248 | ||
249 | keymap = dmi->driver_data; | 249 | keymap = dmi->driver_data; |
250 | for (key = keymap; key->type != KE_END; key++) { | 250 | for (key = keymap; key->type != KE_END; key++) { |
251 | if (key->type == KE_WIFI) { | 251 | if (key->type == KE_WIFI) |
252 | have_wifi = 1; | 252 | have_wifi = 1; |
253 | break; | 253 | else if (key->type == KE_BLUETOOTH) |
254 | } else if (key->type == KE_BLUETOOTH) { | ||
255 | have_bluetooth = 1; | 254 | have_bluetooth = 1; |
256 | break; | ||
257 | } | ||
258 | } | 255 | } |
259 | return 1; | 256 | return 1; |
260 | } | 257 | } |
@@ -389,7 +386,16 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
389 | }, | 386 | }, |
390 | .driver_data = keymap_acer_travelmate_240 | 387 | .driver_data = keymap_acer_travelmate_240 |
391 | }, | 388 | }, |
392 | { | 389 | { |
390 | .callback = dmi_matched, | ||
391 | .ident = "Acer TravelMate 2424NWXCi", | ||
392 | .matches = { | ||
393 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
394 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"), | ||
395 | }, | ||
396 | .driver_data = keymap_acer_travelmate_240 | ||
397 | }, | ||
398 | { | ||
393 | .callback = dmi_matched, | 399 | .callback = dmi_matched, |
394 | .ident = "AOpen 1559AS", | 400 | .ident = "AOpen 1559AS", |
395 | .matches = { | 401 | .matches = { |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 070d75330afd..450b68a619fd 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #define ALPS_PASS 0x20 | 36 | #define ALPS_PASS 0x20 |
37 | #define ALPS_FW_BK_2 0x40 | 37 | #define ALPS_FW_BK_2 0x40 |
38 | 38 | ||
39 | static struct alps_model_info alps_model_data[] = { | 39 | static const struct alps_model_info alps_model_data[] = { |
40 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ | 40 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ |
41 | { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, | 41 | { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, |
42 | { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, | 42 | { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, |
@@ -209,10 +209,10 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse, struct pt_regs * | |||
209 | return PSMOUSE_GOOD_DATA; | 209 | return PSMOUSE_GOOD_DATA; |
210 | } | 210 | } |
211 | 211 | ||
212 | static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) | 212 | static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) |
213 | { | 213 | { |
214 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 214 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
215 | unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; | 215 | static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; |
216 | unsigned char param[4]; | 216 | unsigned char param[4]; |
217 | int i; | 217 | int i; |
218 | 218 | ||
@@ -504,7 +504,7 @@ init_fail: | |||
504 | int alps_detect(struct psmouse *psmouse, int set_properties) | 504 | int alps_detect(struct psmouse *psmouse, int set_properties) |
505 | { | 505 | { |
506 | int version; | 506 | int version; |
507 | struct alps_model_info *model; | 507 | const struct alps_model_info *model; |
508 | 508 | ||
509 | if (!(model = alps_get_model(psmouse, &version))) | 509 | if (!(model = alps_get_model(psmouse, &version))) |
510 | return -1; | 510 | return -1; |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index e428f8d5d12e..69db7325a494 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
@@ -25,7 +25,7 @@ struct alps_data { | |||
25 | struct input_dev *dev2; /* Relative device */ | 25 | struct input_dev *dev2; /* Relative device */ |
26 | char name[32]; /* Name */ | 26 | char name[32]; /* Name */ |
27 | char phys[32]; /* Phys */ | 27 | char phys[32]; /* Phys */ |
28 | struct alps_model_info *i; /* Info */ | 28 | const struct alps_model_info *i;/* Info */ |
29 | int prev_fin; /* Finger bit from previous packet */ | 29 | int prev_fin; /* Finger bit from previous packet */ |
30 | }; | 30 | }; |
31 | 31 | ||
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index c14395ba7980..5e9d25067513 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
@@ -115,13 +115,15 @@ static int lifebook_absolute_mode(struct psmouse *psmouse) | |||
115 | 115 | ||
116 | static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution) | 116 | static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution) |
117 | { | 117 | { |
118 | unsigned char params[] = { 0, 1, 2, 2, 3 }; | 118 | static const unsigned char params[] = { 0, 1, 2, 2, 3 }; |
119 | unsigned char p; | ||
119 | 120 | ||
120 | if (resolution == 0 || resolution > 400) | 121 | if (resolution == 0 || resolution > 400) |
121 | resolution = 400; | 122 | resolution = 400; |
122 | 123 | ||
123 | ps2_command(&psmouse->ps2dev, ¶ms[resolution / 100], PSMOUSE_CMD_SETRES); | 124 | p = params[resolution / 100]; |
124 | psmouse->resolution = 50 << params[resolution / 100]; | 125 | ps2_command(&psmouse->ps2dev, &p, PSMOUSE_CMD_SETRES); |
126 | psmouse->resolution = 50 << p; | ||
125 | } | 127 | } |
126 | 128 | ||
127 | static void lifebook_disconnect(struct psmouse *psmouse) | 129 | static void lifebook_disconnect(struct psmouse *psmouse) |
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 54b696cfe1e3..7972eecbcfe4 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
@@ -30,9 +30,9 @@ | |||
30 | #define PS2PP_NAV_BTN 0x20 | 30 | #define PS2PP_NAV_BTN 0x20 |
31 | 31 | ||
32 | struct ps2pp_info { | 32 | struct ps2pp_info { |
33 | const int model; | 33 | u8 model; |
34 | unsigned const int kind; | 34 | u8 kind; |
35 | unsigned const int features; | 35 | u16 features; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | /* | 38 | /* |
@@ -199,9 +199,9 @@ static void ps2pp_disconnect(struct psmouse *psmouse) | |||
199 | device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll.dattr); | 199 | device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll.dattr); |
200 | } | 200 | } |
201 | 201 | ||
202 | static struct ps2pp_info *get_model_info(unsigned char model) | 202 | static const struct ps2pp_info *get_model_info(unsigned char model) |
203 | { | 203 | { |
204 | static struct ps2pp_info ps2pp_list[] = { | 204 | static const struct ps2pp_info ps2pp_list[] = { |
205 | { 12, 0, PS2PP_SIDE_BTN}, | 205 | { 12, 0, PS2PP_SIDE_BTN}, |
206 | { 13, 0, 0 }, | 206 | { 13, 0, 0 }, |
207 | { 15, PS2PP_KIND_MX, /* MX1000 */ | 207 | { 15, PS2PP_KIND_MX, /* MX1000 */ |
@@ -215,6 +215,7 @@ static struct ps2pp_info *get_model_info(unsigned char model) | |||
215 | { 51, 0, 0 }, | 215 | { 51, 0, 0 }, |
216 | { 52, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, | 216 | { 52, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, |
217 | { 53, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, | 217 | { 53, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, |
218 | { 56, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, /* Cordless MouseMan Wheel */ | ||
218 | { 61, PS2PP_KIND_MX, /* MX700 */ | 219 | { 61, PS2PP_KIND_MX, /* MX700 */ |
219 | PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | | 220 | PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | |
220 | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, | 221 | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, |
@@ -244,12 +245,11 @@ static struct ps2pp_info *get_model_info(unsigned char model) | |||
244 | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, | 245 | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, |
245 | { 114, PS2PP_KIND_MX, /* MX310 */ | 246 | { 114, PS2PP_KIND_MX, /* MX310 */ |
246 | PS2PP_WHEEL | PS2PP_SIDE_BTN | | 247 | PS2PP_WHEEL | PS2PP_SIDE_BTN | |
247 | PS2PP_TASK_BTN | PS2PP_EXTRA_BTN }, | 248 | PS2PP_TASK_BTN | PS2PP_EXTRA_BTN } |
248 | { } | ||
249 | }; | 249 | }; |
250 | int i; | 250 | int i; |
251 | 251 | ||
252 | for (i = 0; ps2pp_list[i].model; i++) | 252 | for (i = 0; i < ARRAY_SIZE(ps2pp_list); i++) |
253 | if (model == ps2pp_list[i].model) | 253 | if (model == ps2pp_list[i].model) |
254 | return &ps2pp_list[i]; | 254 | return &ps2pp_list[i]; |
255 | 255 | ||
@@ -261,7 +261,8 @@ static struct ps2pp_info *get_model_info(unsigned char model) | |||
261 | * Set up input device's properties based on the detected mouse model. | 261 | * Set up input device's properties based on the detected mouse model. |
262 | */ | 262 | */ |
263 | 263 | ||
264 | static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_info *model_info, | 264 | static void ps2pp_set_model_properties(struct psmouse *psmouse, |
265 | const struct ps2pp_info *model_info, | ||
265 | int using_ps2pp) | 266 | int using_ps2pp) |
266 | { | 267 | { |
267 | struct input_dev *input_dev = psmouse->dev; | 268 | struct input_dev *input_dev = psmouse->dev; |
@@ -327,7 +328,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) | |||
327 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 328 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
328 | unsigned char param[4]; | 329 | unsigned char param[4]; |
329 | unsigned char model, buttons; | 330 | unsigned char model, buttons; |
330 | struct ps2pp_info *model_info; | 331 | const struct ps2pp_info *model_info; |
331 | int use_ps2pp = 0; | 332 | int use_ps2pp = 0; |
332 | 333 | ||
333 | param[0] = 0; | 334 | param[0] = 0; |
@@ -349,7 +350,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) | |||
349 | /* | 350 | /* |
350 | * Do Logitech PS2++ / PS2T++ magic init. | 351 | * Do Logitech PS2++ / PS2T++ magic init. |
351 | */ | 352 | */ |
352 | if (model == 97) { /* Touch Pad 3 */ | 353 | if (model_info->kind == PS2PP_KIND_TP3) { /* Touch Pad 3 */ |
353 | 354 | ||
354 | /* Unprotect RAM */ | 355 | /* Unprotect RAM */ |
355 | param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; | 356 | param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 343afa38f4c2..9fb7eb6b0f71 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -112,8 +112,8 @@ static struct workqueue_struct *kpsmoused_wq; | |||
112 | 112 | ||
113 | struct psmouse_protocol { | 113 | struct psmouse_protocol { |
114 | enum psmouse_type type; | 114 | enum psmouse_type type; |
115 | char *name; | 115 | const char *name; |
116 | char *alias; | 116 | const char *alias; |
117 | int maxproto; | 117 | int maxproto; |
118 | int (*detect)(struct psmouse *, int); | 118 | int (*detect)(struct psmouse *, int); |
119 | int (*init)(struct psmouse *); | 119 | int (*init)(struct psmouse *); |
@@ -507,15 +507,17 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties) | |||
507 | { | 507 | { |
508 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 508 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
509 | unsigned char param[2]; | 509 | unsigned char param[2]; |
510 | unsigned char seq[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20, 0 }; | 510 | static const unsigned char seq[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 }; |
511 | int i; | 511 | int i; |
512 | 512 | ||
513 | param[0] = 10; | 513 | param[0] = 10; |
514 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | 514 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); |
515 | param[0] = 0; | 515 | param[0] = 0; |
516 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); | 516 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); |
517 | for (i = 0; seq[i]; i++) | 517 | for (i = 0; i < ARRAY_SIZE(seq); i++) { |
518 | ps2_command(ps2dev, seq + i, PSMOUSE_CMD_SETRATE); | 518 | param[0] = seq[i]; |
519 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | ||
520 | } | ||
519 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); | 521 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); |
520 | 522 | ||
521 | if (param[0] != 2) | 523 | if (param[0] != 2) |
@@ -652,7 +654,7 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
652 | return PSMOUSE_PS2; | 654 | return PSMOUSE_PS2; |
653 | } | 655 | } |
654 | 656 | ||
655 | static struct psmouse_protocol psmouse_protocols[] = { | 657 | static const struct psmouse_protocol psmouse_protocols[] = { |
656 | { | 658 | { |
657 | .type = PSMOUSE_PS2, | 659 | .type = PSMOUSE_PS2, |
658 | .name = "PS/2", | 660 | .name = "PS/2", |
@@ -726,7 +728,7 @@ static struct psmouse_protocol psmouse_protocols[] = { | |||
726 | }, | 728 | }, |
727 | }; | 729 | }; |
728 | 730 | ||
729 | static struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type) | 731 | static const struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type) |
730 | { | 732 | { |
731 | int i; | 733 | int i; |
732 | 734 | ||
@@ -738,9 +740,9 @@ static struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type) | |||
738 | return &psmouse_protocols[0]; | 740 | return &psmouse_protocols[0]; |
739 | } | 741 | } |
740 | 742 | ||
741 | static struct psmouse_protocol *psmouse_protocol_by_name(const char *name, size_t len) | 743 | static const struct psmouse_protocol *psmouse_protocol_by_name(const char *name, size_t len) |
742 | { | 744 | { |
743 | struct psmouse_protocol *p; | 745 | const struct psmouse_protocol *p; |
744 | int i; | 746 | int i; |
745 | 747 | ||
746 | for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) { | 748 | for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) { |
@@ -795,13 +797,15 @@ static int psmouse_probe(struct psmouse *psmouse) | |||
795 | 797 | ||
796 | void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution) | 798 | void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution) |
797 | { | 799 | { |
798 | unsigned char params[] = { 0, 1, 2, 2, 3 }; | 800 | static const unsigned char params[] = { 0, 1, 2, 2, 3 }; |
801 | unsigned char p; | ||
799 | 802 | ||
800 | if (resolution == 0 || resolution > 200) | 803 | if (resolution == 0 || resolution > 200) |
801 | resolution = 200; | 804 | resolution = 200; |
802 | 805 | ||
803 | ps2_command(&psmouse->ps2dev, ¶ms[resolution / 50], PSMOUSE_CMD_SETRES); | 806 | p = params[resolution / 50]; |
804 | psmouse->resolution = 25 << params[resolution / 50]; | 807 | ps2_command(&psmouse->ps2dev, &p, PSMOUSE_CMD_SETRES); |
808 | psmouse->resolution = 25 << p; | ||
805 | } | 809 | } |
806 | 810 | ||
807 | /* | 811 | /* |
@@ -810,12 +814,14 @@ void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution) | |||
810 | 814 | ||
811 | static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate) | 815 | static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate) |
812 | { | 816 | { |
813 | unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10, 0 }; | 817 | static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10, 0 }; |
818 | unsigned char r; | ||
814 | int i = 0; | 819 | int i = 0; |
815 | 820 | ||
816 | while (rates[i] > rate) i++; | 821 | while (rates[i] > rate) i++; |
817 | ps2_command(&psmouse->ps2dev, &rates[i], PSMOUSE_CMD_SETRATE); | 822 | r = rates[i]; |
818 | psmouse->rate = rates[i]; | 823 | ps2_command(&psmouse->ps2dev, &r, PSMOUSE_CMD_SETRATE); |
824 | psmouse->rate = r; | ||
819 | } | 825 | } |
820 | 826 | ||
821 | /* | 827 | /* |
@@ -1031,7 +1037,7 @@ static void psmouse_disconnect(struct serio *serio) | |||
1031 | mutex_unlock(&psmouse_mutex); | 1037 | mutex_unlock(&psmouse_mutex); |
1032 | } | 1038 | } |
1033 | 1039 | ||
1034 | static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto) | 1040 | static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse_protocol *proto) |
1035 | { | 1041 | { |
1036 | struct input_dev *input_dev = psmouse->dev; | 1042 | struct input_dev *input_dev = psmouse->dev; |
1037 | 1043 | ||
@@ -1362,7 +1368,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co | |||
1362 | struct serio *serio = psmouse->ps2dev.serio; | 1368 | struct serio *serio = psmouse->ps2dev.serio; |
1363 | struct psmouse *parent = NULL; | 1369 | struct psmouse *parent = NULL; |
1364 | struct input_dev *new_dev; | 1370 | struct input_dev *new_dev; |
1365 | struct psmouse_protocol *proto; | 1371 | const struct psmouse_protocol *proto; |
1366 | int retry = 0; | 1372 | int retry = 0; |
1367 | 1373 | ||
1368 | if (!(proto = psmouse_protocol_by_name(buf, count))) | 1374 | if (!(proto = psmouse_protocol_by_name(buf, count))) |
@@ -1459,7 +1465,7 @@ static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, | |||
1459 | 1465 | ||
1460 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) | 1466 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) |
1461 | { | 1467 | { |
1462 | struct psmouse_protocol *proto; | 1468 | const struct psmouse_protocol *proto; |
1463 | 1469 | ||
1464 | if (!val) | 1470 | if (!val) |
1465 | return -EINVAL; | 1471 | return -EINVAL; |
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c index 0023501a5b63..680b32353884 100644 --- a/drivers/input/mouse/sermouse.c +++ b/drivers/input/mouse/sermouse.c | |||
@@ -42,7 +42,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |||
42 | MODULE_DESCRIPTION(DRIVER_DESC); | 42 | MODULE_DESCRIPTION(DRIVER_DESC); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | 44 | ||
45 | static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse", | 45 | static const char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse", |
46 | "Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse", | 46 | "Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse", |
47 | "Logitech MZ++ Mouse"}; | 47 | "Logitech MZ++ Mouse"}; |
48 | 48 | ||
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index ad5d0a85e960..392108c436ba 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -430,11 +430,11 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
430 | 430 | ||
431 | static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type) | 431 | static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type) |
432 | { | 432 | { |
433 | static unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 }; | 433 | static const unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 }; |
434 | static unsigned char newabs_rel_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 }; | 434 | static const unsigned char newabs_rel_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 }; |
435 | static unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 }; | 435 | static const unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 }; |
436 | static unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 }; | 436 | static const unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 }; |
437 | static unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 }; | 437 | static const unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 }; |
438 | 438 | ||
439 | if (idx < 0 || idx > 4) | 439 | if (idx < 0 || idx > 4) |
440 | return 0; | 440 | return 0; |
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 1f851acab30d..a22a74a2a3dc 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
@@ -614,7 +614,7 @@ static unsigned int mousedev_poll(struct file *file, poll_table *wait) | |||
614 | (list->mousedev->exist ? 0 : (POLLHUP | POLLERR)); | 614 | (list->mousedev->exist ? 0 : (POLLHUP | POLLERR)); |
615 | } | 615 | } |
616 | 616 | ||
617 | static struct file_operations mousedev_fops = { | 617 | static const struct file_operations mousedev_fops = { |
618 | .owner = THIS_MODULE, | 618 | .owner = THIS_MODULE, |
619 | .read = mousedev_read, | 619 | .read = mousedev_read, |
620 | .write = mousedev_write, | 620 | .write = mousedev_write, |
@@ -624,7 +624,8 @@ static struct file_operations mousedev_fops = { | |||
624 | .fasync = mousedev_fasync, | 624 | .fasync = mousedev_fasync, |
625 | }; | 625 | }; |
626 | 626 | ||
627 | static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id) | 627 | static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, |
628 | const struct input_device_id *id) | ||
628 | { | 629 | { |
629 | struct mousedev *mousedev; | 630 | struct mousedev *mousedev; |
630 | struct class_device *cdev; | 631 | struct class_device *cdev; |
@@ -688,7 +689,7 @@ static void mousedev_disconnect(struct input_handle *handle) | |||
688 | } | 689 | } |
689 | } | 690 | } |
690 | 691 | ||
691 | static struct input_device_id mousedev_ids[] = { | 692 | static const struct input_device_id mousedev_ids[] = { |
692 | { | 693 | { |
693 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, | 694 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, |
694 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, | 695 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, |
@@ -737,7 +738,12 @@ static int psaux_registered; | |||
737 | 738 | ||
738 | static int __init mousedev_init(void) | 739 | static int __init mousedev_init(void) |
739 | { | 740 | { |
740 | input_register_handler(&mousedev_handler); | 741 | struct class_device *cdev; |
742 | int error; | ||
743 | |||
744 | error = input_register_handler(&mousedev_handler); | ||
745 | if (error) | ||
746 | return error; | ||
741 | 747 | ||
742 | memset(&mousedev_mix, 0, sizeof(struct mousedev)); | 748 | memset(&mousedev_mix, 0, sizeof(struct mousedev)); |
743 | INIT_LIST_HEAD(&mousedev_mix.list); | 749 | INIT_LIST_HEAD(&mousedev_mix.list); |
@@ -746,12 +752,20 @@ static int __init mousedev_init(void) | |||
746 | mousedev_mix.exist = 1; | 752 | mousedev_mix.exist = 1; |
747 | mousedev_mix.minor = MOUSEDEV_MIX; | 753 | mousedev_mix.minor = MOUSEDEV_MIX; |
748 | 754 | ||
749 | class_device_create(&input_class, NULL, | 755 | cdev = class_device_create(&input_class, NULL, |
750 | MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice"); | 756 | MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice"); |
757 | if (IS_ERR(cdev)) { | ||
758 | input_unregister_handler(&mousedev_handler); | ||
759 | return PTR_ERR(cdev); | ||
760 | } | ||
751 | 761 | ||
752 | #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX | 762 | #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX |
753 | if (!(psaux_registered = !misc_register(&psaux_mouse))) | 763 | error = misc_register(&psaux_mouse); |
754 | printk(KERN_WARNING "mice: could not misc_register the device\n"); | 764 | if (error) |
765 | printk(KERN_WARNING "mice: could not register psaux device, " | ||
766 | "error: %d\n", error); | ||
767 | else | ||
768 | psaux_registered = 1; | ||
755 | #endif | 769 | #endif |
756 | 770 | ||
757 | printk(KERN_INFO "mice: PS/2 mouse device common for all mice\n"); | 771 | printk(KERN_INFO "mice: PS/2 mouse device common for all mice\n"); |
diff --git a/drivers/input/power.c b/drivers/input/power.c index 51a519e24b6d..ee82464a2fa7 100644 --- a/drivers/input/power.c +++ b/drivers/input/power.c | |||
@@ -98,7 +98,7 @@ static void power_event(struct input_handle *handle, unsigned int type, | |||
98 | 98 | ||
99 | static struct input_handle *power_connect(struct input_handler *handler, | 99 | static struct input_handle *power_connect(struct input_handler *handler, |
100 | struct input_dev *dev, | 100 | struct input_dev *dev, |
101 | struct input_device_id *id) | 101 | const struct input_device_id *id) |
102 | { | 102 | { |
103 | struct input_handle *handle; | 103 | struct input_handle *handle; |
104 | 104 | ||
@@ -120,7 +120,7 @@ static void power_disconnect(struct input_handle *handle) | |||
120 | kfree(handle); | 120 | kfree(handle); |
121 | } | 121 | } |
122 | 122 | ||
123 | static struct input_device_id power_ids[] = { | 123 | static const struct input_device_id power_ids[] = { |
124 | { | 124 | { |
125 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, | 125 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, |
126 | .evbit = { BIT(EV_KEY) }, | 126 | .evbit = { BIT(EV_KEY) }, |
@@ -150,8 +150,7 @@ static struct input_handler power_handler = { | |||
150 | 150 | ||
151 | static int __init power_init(void) | 151 | static int __init power_init(void) |
152 | { | 152 | { |
153 | input_register_handler(&power_handler); | 153 | return input_register_handler(&power_handler); |
154 | return 0; | ||
155 | } | 154 | } |
156 | 155 | ||
157 | static void __exit power_exit(void) | 156 | static void __exit power_exit(void) |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index f606e96bc2f4..8738edda6610 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -160,6 +160,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
160 | }, | 160 | }, |
161 | }, | 161 | }, |
162 | { | 162 | { |
163 | .ident = "Toshiba Equium A110", | ||
164 | .matches = { | ||
165 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
166 | DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"), | ||
167 | }, | ||
168 | }, | ||
169 | { | ||
163 | .ident = "Alienware Sentia", | 170 | .ident = "Alienware Sentia", |
164 | .matches = { | 171 | .matches = { |
165 | DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), | 172 | DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), |
@@ -180,6 +187,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
180 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), | 187 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), |
181 | }, | 188 | }, |
182 | }, | 189 | }, |
190 | { | ||
191 | .ident = "Amoi M636/A737", | ||
192 | .matches = { | ||
193 | DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."), | ||
194 | DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"), | ||
195 | }, | ||
196 | }, | ||
183 | { } | 197 | { } |
184 | }; | 198 | }; |
185 | 199 | ||
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 06a3f25657dd..1bb0c76a9259 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -90,46 +90,24 @@ static DEFINE_SPINLOCK(i8042_lock); | |||
90 | struct i8042_port { | 90 | struct i8042_port { |
91 | struct serio *serio; | 91 | struct serio *serio; |
92 | int irq; | 92 | int irq; |
93 | unsigned char disable; | ||
94 | unsigned char irqen; | ||
95 | unsigned char exists; | 93 | unsigned char exists; |
96 | signed char mux; | 94 | signed char mux; |
97 | char name[8]; | ||
98 | }; | 95 | }; |
99 | 96 | ||
100 | #define I8042_KBD_PORT_NO 0 | 97 | #define I8042_KBD_PORT_NO 0 |
101 | #define I8042_AUX_PORT_NO 1 | 98 | #define I8042_AUX_PORT_NO 1 |
102 | #define I8042_MUX_PORT_NO 2 | 99 | #define I8042_MUX_PORT_NO 2 |
103 | #define I8042_NUM_PORTS (I8042_NUM_MUX_PORTS + 2) | 100 | #define I8042_NUM_PORTS (I8042_NUM_MUX_PORTS + 2) |
104 | static struct i8042_port i8042_ports[I8042_NUM_PORTS] = { | 101 | |
105 | { | 102 | static struct i8042_port i8042_ports[I8042_NUM_PORTS]; |
106 | .disable = I8042_CTR_KBDDIS, | ||
107 | .irqen = I8042_CTR_KBDINT, | ||
108 | .mux = -1, | ||
109 | .name = "KBD", | ||
110 | }, | ||
111 | { | ||
112 | .disable = I8042_CTR_AUXDIS, | ||
113 | .irqen = I8042_CTR_AUXINT, | ||
114 | .mux = -1, | ||
115 | .name = "AUX", | ||
116 | } | ||
117 | }; | ||
118 | 103 | ||
119 | static unsigned char i8042_initial_ctr; | 104 | static unsigned char i8042_initial_ctr; |
120 | static unsigned char i8042_ctr; | 105 | static unsigned char i8042_ctr; |
121 | static unsigned char i8042_mux_open; | ||
122 | static unsigned char i8042_mux_present; | 106 | static unsigned char i8042_mux_present; |
123 | static struct timer_list i8042_timer; | 107 | static unsigned char i8042_kbd_irq_registered; |
108 | static unsigned char i8042_aux_irq_registered; | ||
124 | static struct platform_device *i8042_platform_device; | 109 | static struct platform_device *i8042_platform_device; |
125 | 110 | ||
126 | |||
127 | /* | ||
128 | * Shared IRQ's require a device pointer, but this driver doesn't support | ||
129 | * multiple devices | ||
130 | */ | ||
131 | #define i8042_request_irq_cookie (&i8042_timer) | ||
132 | |||
133 | static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 111 | static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
134 | 112 | ||
135 | /* | 113 | /* |
@@ -141,6 +119,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs); | |||
141 | static int i8042_wait_read(void) | 119 | static int i8042_wait_read(void) |
142 | { | 120 | { |
143 | int i = 0; | 121 | int i = 0; |
122 | |||
144 | while ((~i8042_read_status() & I8042_STR_OBF) && (i < I8042_CTL_TIMEOUT)) { | 123 | while ((~i8042_read_status() & I8042_STR_OBF) && (i < I8042_CTL_TIMEOUT)) { |
145 | udelay(50); | 124 | udelay(50); |
146 | i++; | 125 | i++; |
@@ -151,6 +130,7 @@ static int i8042_wait_read(void) | |||
151 | static int i8042_wait_write(void) | 130 | static int i8042_wait_write(void) |
152 | { | 131 | { |
153 | int i = 0; | 132 | int i = 0; |
133 | |||
154 | while ((i8042_read_status() & I8042_STR_IBF) && (i < I8042_CTL_TIMEOUT)) { | 134 | while ((i8042_read_status() & I8042_STR_IBF) && (i < I8042_CTL_TIMEOUT)) { |
155 | udelay(50); | 135 | udelay(50); |
156 | i++; | 136 | i++; |
@@ -192,48 +172,57 @@ static int i8042_flush(void) | |||
192 | * encoded in bits 8-11 of the command number. | 172 | * encoded in bits 8-11 of the command number. |
193 | */ | 173 | */ |
194 | 174 | ||
195 | static int i8042_command(unsigned char *param, int command) | 175 | static int __i8042_command(unsigned char *param, int command) |
196 | { | 176 | { |
197 | unsigned long flags; | 177 | int i, error; |
198 | int i, retval, auxerr = 0; | ||
199 | 178 | ||
200 | if (i8042_noloop && command == I8042_CMD_AUX_LOOP) | 179 | if (i8042_noloop && command == I8042_CMD_AUX_LOOP) |
201 | return -1; | 180 | return -1; |
202 | 181 | ||
203 | spin_lock_irqsave(&i8042_lock, flags); | 182 | error = i8042_wait_write(); |
204 | 183 | if (error) | |
205 | if ((retval = i8042_wait_write())) | 184 | return error; |
206 | goto out; | ||
207 | 185 | ||
208 | dbg("%02x -> i8042 (command)", command & 0xff); | 186 | dbg("%02x -> i8042 (command)", command & 0xff); |
209 | i8042_write_command(command & 0xff); | 187 | i8042_write_command(command & 0xff); |
210 | 188 | ||
211 | for (i = 0; i < ((command >> 12) & 0xf); i++) { | 189 | for (i = 0; i < ((command >> 12) & 0xf); i++) { |
212 | if ((retval = i8042_wait_write())) | 190 | error = i8042_wait_write(); |
213 | goto out; | 191 | if (error) |
192 | return error; | ||
214 | dbg("%02x -> i8042 (parameter)", param[i]); | 193 | dbg("%02x -> i8042 (parameter)", param[i]); |
215 | i8042_write_data(param[i]); | 194 | i8042_write_data(param[i]); |
216 | } | 195 | } |
217 | 196 | ||
218 | for (i = 0; i < ((command >> 8) & 0xf); i++) { | 197 | for (i = 0; i < ((command >> 8) & 0xf); i++) { |
219 | if ((retval = i8042_wait_read())) | 198 | error = i8042_wait_read(); |
220 | goto out; | 199 | if (error) { |
200 | dbg(" -- i8042 (timeout)"); | ||
201 | return error; | ||
202 | } | ||
221 | 203 | ||
222 | if (command == I8042_CMD_AUX_LOOP && | 204 | if (command == I8042_CMD_AUX_LOOP && |
223 | !(i8042_read_status() & I8042_STR_AUXDATA)) { | 205 | !(i8042_read_status() & I8042_STR_AUXDATA)) { |
224 | retval = auxerr = -1; | 206 | dbg(" -- i8042 (auxerr)"); |
225 | goto out; | 207 | return -1; |
226 | } | 208 | } |
227 | 209 | ||
228 | param[i] = i8042_read_data(); | 210 | param[i] = i8042_read_data(); |
229 | dbg("%02x <- i8042 (return)", param[i]); | 211 | dbg("%02x <- i8042 (return)", param[i]); |
230 | } | 212 | } |
231 | 213 | ||
232 | if (retval) | 214 | return 0; |
233 | dbg(" -- i8042 (%s)", auxerr ? "auxerr" : "timeout"); | 215 | } |
234 | 216 | ||
235 | out: | 217 | static int i8042_command(unsigned char *param, int command) |
218 | { | ||
219 | unsigned long flags; | ||
220 | int retval; | ||
221 | |||
222 | spin_lock_irqsave(&i8042_lock, flags); | ||
223 | retval = __i8042_command(param, command); | ||
236 | spin_unlock_irqrestore(&i8042_lock, flags); | 224 | spin_unlock_irqrestore(&i8042_lock, flags); |
225 | |||
237 | return retval; | 226 | return retval; |
238 | } | 227 | } |
239 | 228 | ||
@@ -248,7 +237,7 @@ static int i8042_kbd_write(struct serio *port, unsigned char c) | |||
248 | 237 | ||
249 | spin_lock_irqsave(&i8042_lock, flags); | 238 | spin_lock_irqsave(&i8042_lock, flags); |
250 | 239 | ||
251 | if(!(retval = i8042_wait_write())) { | 240 | if (!(retval = i8042_wait_write())) { |
252 | dbg("%02x -> i8042 (kbd-data)", c); | 241 | dbg("%02x -> i8042 (kbd-data)", c); |
253 | i8042_write_data(c); | 242 | i8042_write_data(c); |
254 | } | 243 | } |
@@ -287,100 +276,6 @@ static int i8042_aux_write(struct serio *serio, unsigned char c) | |||
287 | } | 276 | } |
288 | 277 | ||
289 | /* | 278 | /* |
290 | * i8042_activate_port() enables port on a chip. | ||
291 | */ | ||
292 | |||
293 | static int i8042_activate_port(struct i8042_port *port) | ||
294 | { | ||
295 | if (!port->serio) | ||
296 | return -1; | ||
297 | |||
298 | i8042_flush(); | ||
299 | |||
300 | /* | ||
301 | * Enable port again here because it is disabled if we are | ||
302 | * resuming (normally it is enabled already). | ||
303 | */ | ||
304 | i8042_ctr &= ~port->disable; | ||
305 | |||
306 | i8042_ctr |= port->irqen; | ||
307 | |||
308 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | ||
309 | i8042_ctr &= ~port->irqen; | ||
310 | return -1; | ||
311 | } | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | |||
317 | /* | ||
318 | * i8042_open() is called when a port is open by the higher layer. | ||
319 | * It allocates the interrupt and calls i8042_enable_port. | ||
320 | */ | ||
321 | |||
322 | static int i8042_open(struct serio *serio) | ||
323 | { | ||
324 | struct i8042_port *port = serio->port_data; | ||
325 | |||
326 | if (port->mux != -1) | ||
327 | if (i8042_mux_open++) | ||
328 | return 0; | ||
329 | |||
330 | if (request_irq(port->irq, i8042_interrupt, | ||
331 | IRQF_SHARED, "i8042", i8042_request_irq_cookie)) { | ||
332 | printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", port->irq, port->name); | ||
333 | goto irq_fail; | ||
334 | } | ||
335 | |||
336 | if (i8042_activate_port(port)) { | ||
337 | printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", port->name); | ||
338 | goto activate_fail; | ||
339 | } | ||
340 | |||
341 | i8042_interrupt(0, NULL, NULL); | ||
342 | |||
343 | return 0; | ||
344 | |||
345 | activate_fail: | ||
346 | free_irq(port->irq, i8042_request_irq_cookie); | ||
347 | |||
348 | irq_fail: | ||
349 | serio_unregister_port_delayed(serio); | ||
350 | |||
351 | return -1; | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * i8042_close() frees the interrupt, so that it can possibly be used | ||
356 | * by another driver. We never know - if the user doesn't have a mouse, | ||
357 | * the BIOS could have used the AUX interrupt for PCI. | ||
358 | */ | ||
359 | |||
360 | static void i8042_close(struct serio *serio) | ||
361 | { | ||
362 | struct i8042_port *port = serio->port_data; | ||
363 | |||
364 | if (port->mux != -1) | ||
365 | if (--i8042_mux_open) | ||
366 | return; | ||
367 | |||
368 | i8042_ctr &= ~port->irqen; | ||
369 | |||
370 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | ||
371 | printk(KERN_WARNING "i8042.c: Can't write CTR while closing %s.\n", port->name); | ||
372 | /* | ||
373 | * We still want to continue and free IRQ so if more data keeps coming in | ||
374 | * kernel will just ignore the irq. | ||
375 | */ | ||
376 | } | ||
377 | |||
378 | free_irq(port->irq, i8042_request_irq_cookie); | ||
379 | |||
380 | i8042_flush(); | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * i8042_start() is called by serio core when port is about to finish | 279 | * i8042_start() is called by serio core when port is about to finish |
385 | * registering. It will mark port as existing so i8042_interrupt can | 280 | * registering. It will mark port as existing so i8042_interrupt can |
386 | * start sending data through it. | 281 | * start sending data through it. |
@@ -423,8 +318,6 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
423 | unsigned int port_no; | 318 | unsigned int port_no; |
424 | int ret; | 319 | int ret; |
425 | 320 | ||
426 | mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); | ||
427 | |||
428 | spin_lock_irqsave(&i8042_lock, flags); | 321 | spin_lock_irqsave(&i8042_lock, flags); |
429 | str = i8042_read_status(); | 322 | str = i8042_read_status(); |
430 | if (unlikely(~str & I8042_STR_OBF)) { | 323 | if (unlikely(~str & I8042_STR_OBF)) { |
@@ -480,8 +373,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
480 | 373 | ||
481 | port = &i8042_ports[port_no]; | 374 | port = &i8042_ports[port_no]; |
482 | 375 | ||
483 | dbg("%02x <- i8042 (interrupt, %s, %d%s%s)", | 376 | dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", |
484 | data, port->name, irq, | 377 | data, port_no, irq, |
485 | dfl & SERIO_PARITY ? ", bad parity" : "", | 378 | dfl & SERIO_PARITY ? ", bad parity" : "", |
486 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); | 379 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); |
487 | 380 | ||
@@ -494,6 +387,58 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
494 | } | 387 | } |
495 | 388 | ||
496 | /* | 389 | /* |
390 | * i8042_enable_kbd_port enables keybaord port on chip | ||
391 | */ | ||
392 | |||
393 | static int i8042_enable_kbd_port(void) | ||
394 | { | ||
395 | i8042_ctr &= ~I8042_CTR_KBDDIS; | ||
396 | i8042_ctr |= I8042_CTR_KBDINT; | ||
397 | |||
398 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | ||
399 | printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); | ||
400 | return -EIO; | ||
401 | } | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | /* | ||
407 | * i8042_enable_aux_port enables AUX (mouse) port on chip | ||
408 | */ | ||
409 | |||
410 | static int i8042_enable_aux_port(void) | ||
411 | { | ||
412 | i8042_ctr &= ~I8042_CTR_AUXDIS; | ||
413 | i8042_ctr |= I8042_CTR_AUXINT; | ||
414 | |||
415 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | ||
416 | printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); | ||
417 | return -EIO; | ||
418 | } | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * i8042_enable_mux_ports enables 4 individual AUX ports after | ||
425 | * the controller has been switched into Multiplexed mode | ||
426 | */ | ||
427 | |||
428 | static int i8042_enable_mux_ports(void) | ||
429 | { | ||
430 | unsigned char param; | ||
431 | int i; | ||
432 | |||
433 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { | ||
434 | i8042_command(¶m, I8042_CMD_MUX_PFX + i); | ||
435 | i8042_command(¶m, I8042_CMD_AUX_ENABLE); | ||
436 | } | ||
437 | |||
438 | return i8042_enable_aux_port(); | ||
439 | } | ||
440 | |||
441 | /* | ||
497 | * i8042_set_mux_mode checks whether the controller has an active | 442 | * i8042_set_mux_mode checks whether the controller has an active |
498 | * multiplexor and puts the chip into Multiplexed (1) or Legacy (0) mode. | 443 | * multiplexor and puts the chip into Multiplexed (1) or Legacy (0) mode. |
499 | */ | 444 | */ |
@@ -510,8 +455,7 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | |||
510 | 455 | ||
511 | /* | 456 | /* |
512 | * Internal loopback test - send three bytes, they should come back from the | 457 | * Internal loopback test - send three bytes, they should come back from the |
513 | * mouse interface, the last should be version. Note that we negate mouseport | 458 | * mouse interface, the last should be version. |
514 | * command responses for the i8042_check_aux() routine. | ||
515 | */ | 459 | */ |
516 | 460 | ||
517 | param = 0xf0; | 461 | param = 0xf0; |
@@ -530,67 +474,67 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | |||
530 | return 0; | 474 | return 0; |
531 | } | 475 | } |
532 | 476 | ||
533 | |||
534 | /* | 477 | /* |
535 | * i8042_enable_mux_ports enables 4 individual AUX ports after | 478 | * i8042_check_mux() checks whether the controller supports the PS/2 Active |
536 | * the controller has been switched into Multiplexed mode | 479 | * Multiplexing specification by Synaptics, Phoenix, Insyde and |
480 | * LCS/Telegraphics. | ||
537 | */ | 481 | */ |
538 | 482 | ||
539 | static int i8042_enable_mux_ports(void) | 483 | static int __devinit i8042_check_mux(void) |
540 | { | 484 | { |
541 | unsigned char param; | 485 | unsigned char mux_version; |
542 | int i; | 486 | |
487 | if (i8042_set_mux_mode(1, &mux_version)) | ||
488 | return -1; | ||
489 | |||
543 | /* | 490 | /* |
544 | * Disable all muxed ports by disabling AUX. | 491 | * Workaround for interference with USB Legacy emulation |
492 | * that causes a v10.12 MUX to be found. | ||
545 | */ | 493 | */ |
494 | if (mux_version == 0xAC) | ||
495 | return -1; | ||
496 | |||
497 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", | ||
498 | (mux_version >> 4) & 0xf, mux_version & 0xf); | ||
546 | 499 | ||
500 | /* | ||
501 | * Disable all muxed ports by disabling AUX. | ||
502 | */ | ||
547 | i8042_ctr |= I8042_CTR_AUXDIS; | 503 | i8042_ctr |= I8042_CTR_AUXDIS; |
548 | i8042_ctr &= ~I8042_CTR_AUXINT; | 504 | i8042_ctr &= ~I8042_CTR_AUXINT; |
549 | 505 | ||
550 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 506 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
551 | printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n"); | 507 | printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n"); |
552 | return -1; | 508 | return -EIO; |
553 | } | 509 | } |
554 | 510 | ||
555 | /* | 511 | i8042_mux_present = 1; |
556 | * Enable all muxed ports. | ||
557 | */ | ||
558 | |||
559 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { | ||
560 | i8042_command(¶m, I8042_CMD_MUX_PFX + i); | ||
561 | i8042_command(¶m, I8042_CMD_AUX_ENABLE); | ||
562 | } | ||
563 | 512 | ||
564 | return 0; | 513 | return 0; |
565 | } | 514 | } |
566 | 515 | ||
567 | |||
568 | /* | 516 | /* |
569 | * i8042_check_mux() checks whether the controller supports the PS/2 Active | 517 | * The following is used to test AUX IRQ delivery. |
570 | * Multiplexing specification by Synaptics, Phoenix, Insyde and | ||
571 | * LCS/Telegraphics. | ||
572 | */ | 518 | */ |
519 | static struct completion i8042_aux_irq_delivered __devinitdata; | ||
520 | static int i8042_irq_being_tested __devinitdata; | ||
573 | 521 | ||
574 | static int __devinit i8042_check_mux(void) | 522 | static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id, struct pt_regs *regs) |
575 | { | 523 | { |
576 | unsigned char mux_version; | 524 | unsigned long flags; |
577 | 525 | unsigned char str, data; | |
578 | if (i8042_set_mux_mode(1, &mux_version)) | ||
579 | return -1; | ||
580 | |||
581 | /* Workaround for interference with USB Legacy emulation */ | ||
582 | /* that causes a v10.12 MUX to be found. */ | ||
583 | if (mux_version == 0xAC) | ||
584 | return -1; | ||
585 | |||
586 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", | ||
587 | (mux_version >> 4) & 0xf, mux_version & 0xf); | ||
588 | 526 | ||
589 | if (i8042_enable_mux_ports()) | 527 | spin_lock_irqsave(&i8042_lock, flags); |
590 | return -1; | 528 | str = i8042_read_status(); |
529 | if (str & I8042_STR_OBF) { | ||
530 | data = i8042_read_data(); | ||
531 | if (i8042_irq_being_tested && | ||
532 | data == 0xa5 && (str & I8042_STR_AUXDATA)) | ||
533 | complete(&i8042_aux_irq_delivered); | ||
534 | } | ||
535 | spin_unlock_irqrestore(&i8042_lock, flags); | ||
591 | 536 | ||
592 | i8042_mux_present = 1; | 537 | return IRQ_HANDLED; |
593 | return 0; | ||
594 | } | 538 | } |
595 | 539 | ||
596 | 540 | ||
@@ -601,18 +545,10 @@ static int __devinit i8042_check_mux(void) | |||
601 | 545 | ||
602 | static int __devinit i8042_check_aux(void) | 546 | static int __devinit i8042_check_aux(void) |
603 | { | 547 | { |
548 | int retval = -1; | ||
549 | int irq_registered = 0; | ||
550 | unsigned long flags; | ||
604 | unsigned char param; | 551 | unsigned char param; |
605 | static int i8042_check_aux_cookie; | ||
606 | |||
607 | /* | ||
608 | * Check if AUX irq is available. If it isn't, then there is no point | ||
609 | * in trying to detect AUX presence. | ||
610 | */ | ||
611 | |||
612 | if (request_irq(i8042_ports[I8042_AUX_PORT_NO].irq, i8042_interrupt, | ||
613 | IRQF_SHARED, "i8042", &i8042_check_aux_cookie)) | ||
614 | return -1; | ||
615 | free_irq(i8042_ports[I8042_AUX_PORT_NO].irq, &i8042_check_aux_cookie); | ||
616 | 552 | ||
617 | /* | 553 | /* |
618 | * Get rid of bytes in the queue. | 554 | * Get rid of bytes in the queue. |
@@ -637,9 +573,9 @@ static int __devinit i8042_check_aux(void) | |||
637 | * AUX ports, we test for this only when the LOOP command failed. | 573 | * AUX ports, we test for this only when the LOOP command failed. |
638 | */ | 574 | */ |
639 | 575 | ||
640 | if (i8042_command(¶m, I8042_CMD_AUX_TEST) | 576 | if (i8042_command(¶m, I8042_CMD_AUX_TEST) || |
641 | || (param && param != 0xfa && param != 0xff)) | 577 | (param && param != 0xfa && param != 0xff)) |
642 | return -1; | 578 | return -1; |
643 | } | 579 | } |
644 | 580 | ||
645 | /* | 581 | /* |
@@ -659,54 +595,80 @@ static int __devinit i8042_check_aux(void) | |||
659 | return -1; | 595 | return -1; |
660 | 596 | ||
661 | /* | 597 | /* |
662 | * Disable the interface. | 598 | * Test AUX IRQ delivery to make sure BIOS did not grab the IRQ and |
599 | * used it for a PCI card or somethig else. | ||
663 | */ | 600 | */ |
664 | 601 | ||
665 | i8042_ctr |= I8042_CTR_AUXDIS; | 602 | if (i8042_noloop) { |
666 | i8042_ctr &= ~I8042_CTR_AUXINT; | 603 | /* |
604 | * Without LOOP command we can't test AUX IRQ delivery. Assume the port | ||
605 | * is working and hope we are right. | ||
606 | */ | ||
607 | retval = 0; | ||
608 | goto out; | ||
609 | } | ||
667 | 610 | ||
668 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | 611 | if (request_irq(I8042_AUX_IRQ, i8042_aux_test_irq, IRQF_SHARED, |
669 | return -1; | 612 | "i8042", i8042_platform_device)) |
613 | goto out; | ||
670 | 614 | ||
671 | return 0; | 615 | irq_registered = 1; |
672 | } | 616 | |
617 | if (i8042_enable_aux_port()) | ||
618 | goto out; | ||
619 | |||
620 | spin_lock_irqsave(&i8042_lock, flags); | ||
673 | 621 | ||
622 | init_completion(&i8042_aux_irq_delivered); | ||
623 | i8042_irq_being_tested = 1; | ||
624 | |||
625 | param = 0xa5; | ||
626 | retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); | ||
627 | |||
628 | spin_unlock_irqrestore(&i8042_lock, flags); | ||
629 | |||
630 | if (retval) | ||
631 | goto out; | ||
674 | 632 | ||
633 | if (wait_for_completion_timeout(&i8042_aux_irq_delivered, | ||
634 | msecs_to_jiffies(250)) == 0) { | ||
675 | /* | 635 | /* |
676 | * i8042_port_register() marks the device as existing, | 636 | * AUX IRQ was never delivered so we need to flush the controller to |
677 | * registers it, and reports to the user. | 637 | * get rid of the byte we put there; otherwise keyboard may not work. |
678 | */ | 638 | */ |
639 | i8042_flush(); | ||
640 | retval = -1; | ||
641 | } | ||
679 | 642 | ||
680 | static int __devinit i8042_port_register(struct i8042_port *port) | 643 | out: |
681 | { | ||
682 | i8042_ctr &= ~port->disable; | ||
683 | 644 | ||
684 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 645 | /* |
685 | printk(KERN_WARNING "i8042.c: Can't write CTR while registering.\n"); | 646 | * Disable the interface. |
686 | kfree(port->serio); | 647 | */ |
687 | port->serio = NULL; | ||
688 | i8042_ctr |= port->disable; | ||
689 | return -EIO; | ||
690 | } | ||
691 | 648 | ||
692 | printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", | 649 | i8042_ctr |= I8042_CTR_AUXDIS; |
693 | port->name, | 650 | i8042_ctr &= ~I8042_CTR_AUXINT; |
694 | (unsigned long) I8042_DATA_REG, | ||
695 | (unsigned long) I8042_COMMAND_REG, | ||
696 | port->irq); | ||
697 | 651 | ||
698 | serio_register_port(port->serio); | 652 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) |
653 | retval = -1; | ||
699 | 654 | ||
700 | return 0; | 655 | if (irq_registered) |
701 | } | 656 | free_irq(I8042_AUX_IRQ, i8042_platform_device); |
702 | 657 | ||
658 | return retval; | ||
659 | } | ||
703 | 660 | ||
704 | static void i8042_timer_func(unsigned long data) | 661 | static int i8042_controller_check(void) |
705 | { | 662 | { |
706 | i8042_interrupt(0, NULL, NULL); | 663 | if (i8042_flush() == I8042_BUFFER_SIZE) { |
664 | printk(KERN_ERR "i8042.c: No controller found.\n"); | ||
665 | return -ENODEV; | ||
666 | } | ||
667 | |||
668 | return 0; | ||
707 | } | 669 | } |
708 | 670 | ||
709 | static int i8042_ctl_test(void) | 671 | static int i8042_controller_selftest(void) |
710 | { | 672 | { |
711 | unsigned char param; | 673 | unsigned char param; |
712 | 674 | ||
@@ -715,13 +677,13 @@ static int i8042_ctl_test(void) | |||
715 | 677 | ||
716 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { | 678 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { |
717 | printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); | 679 | printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); |
718 | return -1; | 680 | return -ENODEV; |
719 | } | 681 | } |
720 | 682 | ||
721 | if (param != I8042_RET_CTL_TEST) { | 683 | if (param != I8042_RET_CTL_TEST) { |
722 | printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", | 684 | printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", |
723 | param, I8042_RET_CTL_TEST); | 685 | param, I8042_RET_CTL_TEST); |
724 | return -1; | 686 | return -EIO; |
725 | } | 687 | } |
726 | 688 | ||
727 | return 0; | 689 | return 0; |
@@ -738,25 +700,12 @@ static int i8042_controller_init(void) | |||
738 | unsigned long flags; | 700 | unsigned long flags; |
739 | 701 | ||
740 | /* | 702 | /* |
741 | * Test the i8042. We need to know if it thinks it's working correctly | ||
742 | * before doing anything else. | ||
743 | */ | ||
744 | |||
745 | if (i8042_flush() == I8042_BUFFER_SIZE) { | ||
746 | printk(KERN_ERR "i8042.c: No controller found.\n"); | ||
747 | return -1; | ||
748 | } | ||
749 | |||
750 | if (i8042_ctl_test()) | ||
751 | return -1; | ||
752 | |||
753 | /* | ||
754 | * Save the CTR for restoral on unload / reboot. | 703 | * Save the CTR for restoral on unload / reboot. |
755 | */ | 704 | */ |
756 | 705 | ||
757 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) { | 706 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) { |
758 | printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n"); | 707 | printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n"); |
759 | return -1; | 708 | return -EIO; |
760 | } | 709 | } |
761 | 710 | ||
762 | i8042_initial_ctr = i8042_ctr; | 711 | i8042_initial_ctr = i8042_ctr; |
@@ -805,7 +754,7 @@ static int i8042_controller_init(void) | |||
805 | 754 | ||
806 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 755 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
807 | printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n"); | 756 | printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n"); |
808 | return -1; | 757 | return -EIO; |
809 | } | 758 | } |
810 | 759 | ||
811 | return 0; | 760 | return 0; |
@@ -813,15 +762,12 @@ static int i8042_controller_init(void) | |||
813 | 762 | ||
814 | 763 | ||
815 | /* | 764 | /* |
816 | * Reset the controller. | 765 | * Reset the controller and reset CRT to the original value set by BIOS. |
817 | */ | 766 | */ |
767 | |||
818 | static void i8042_controller_reset(void) | 768 | static void i8042_controller_reset(void) |
819 | { | 769 | { |
820 | /* | 770 | i8042_flush(); |
821 | * Reset the controller if requested. | ||
822 | */ | ||
823 | |||
824 | i8042_ctl_test(); | ||
825 | 771 | ||
826 | /* | 772 | /* |
827 | * Disable MUX mode if present. | 773 | * Disable MUX mode if present. |
@@ -831,12 +777,16 @@ static void i8042_controller_reset(void) | |||
831 | i8042_set_mux_mode(0, NULL); | 777 | i8042_set_mux_mode(0, NULL); |
832 | 778 | ||
833 | /* | 779 | /* |
834 | * Restore the original control register setting. | 780 | * Reset the controller if requested. |
835 | */ | 781 | */ |
836 | 782 | ||
837 | i8042_ctr = i8042_initial_ctr; | 783 | i8042_controller_selftest(); |
838 | 784 | ||
839 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | 785 | /* |
786 | * Restore the original control register setting. | ||
787 | */ | ||
788 | |||
789 | if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) | ||
840 | printk(KERN_WARNING "i8042.c: Can't restore CTR.\n"); | 790 | printk(KERN_WARNING "i8042.c: Can't restore CTR.\n"); |
841 | } | 791 | } |
842 | 792 | ||
@@ -850,14 +800,12 @@ static void i8042_controller_cleanup(void) | |||
850 | { | 800 | { |
851 | int i; | 801 | int i; |
852 | 802 | ||
853 | i8042_flush(); | ||
854 | |||
855 | /* | 803 | /* |
856 | * Reset anything that is connected to the ports. | 804 | * Reset anything that is connected to the ports. |
857 | */ | 805 | */ |
858 | 806 | ||
859 | for (i = 0; i < I8042_NUM_PORTS; i++) | 807 | for (i = 0; i < I8042_NUM_PORTS; i++) |
860 | if (i8042_ports[i].exists) | 808 | if (i8042_ports[i].serio) |
861 | serio_cleanup(i8042_ports[i].serio); | 809 | serio_cleanup(i8042_ports[i].serio); |
862 | 810 | ||
863 | i8042_controller_reset(); | 811 | i8042_controller_reset(); |
@@ -913,8 +861,7 @@ static long i8042_panic_blink(long count) | |||
913 | 861 | ||
914 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) | 862 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) |
915 | { | 863 | { |
916 | del_timer_sync(&i8042_timer); | 864 | i8042_controller_cleanup(); |
917 | i8042_controller_reset(); | ||
918 | 865 | ||
919 | return 0; | 866 | return 0; |
920 | } | 867 | } |
@@ -926,33 +873,39 @@ static int i8042_suspend(struct platform_device *dev, pm_message_t state) | |||
926 | 873 | ||
927 | static int i8042_resume(struct platform_device *dev) | 874 | static int i8042_resume(struct platform_device *dev) |
928 | { | 875 | { |
929 | int i; | 876 | int error; |
930 | 877 | ||
931 | if (i8042_ctl_test()) | 878 | error = i8042_controller_check(); |
932 | return -1; | 879 | if (error) |
880 | return error; | ||
933 | 881 | ||
934 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 882 | error = i8042_controller_selftest(); |
935 | printk(KERN_ERR "i8042: Can't write CTR\n"); | 883 | if (error) |
936 | return -1; | 884 | return error; |
937 | } | ||
938 | |||
939 | if (i8042_mux_present) | ||
940 | if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports()) | ||
941 | printk(KERN_WARNING "i8042: failed to resume active multiplexor, mouse won't work.\n"); | ||
942 | 885 | ||
943 | /* | 886 | /* |
944 | * Activate all ports. | 887 | * Restore pre-resume CTR value and disable all ports |
945 | */ | 888 | */ |
946 | 889 | ||
947 | for (i = 0; i < I8042_NUM_PORTS; i++) | 890 | i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS; |
948 | i8042_activate_port(&i8042_ports[i]); | 891 | i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT); |
892 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | ||
893 | printk(KERN_ERR "i8042: Can't write CTR to resume\n"); | ||
894 | return -EIO; | ||
895 | } | ||
949 | 896 | ||
950 | /* | 897 | if (i8042_mux_present) { |
951 | * Restart timer (for polling "stuck" data) | 898 | if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports()) |
952 | */ | 899 | printk(KERN_WARNING |
953 | mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); | 900 | "i8042: failed to resume active multiplexor, " |
901 | "mouse won't work.\n"); | ||
902 | } else if (i8042_ports[I8042_AUX_PORT_NO].serio) | ||
903 | i8042_enable_aux_port(); | ||
954 | 904 | ||
955 | panic_blink = i8042_panic_blink; | 905 | if (i8042_ports[I8042_KBD_PORT_NO].serio) |
906 | i8042_enable_kbd_port(); | ||
907 | |||
908 | i8042_interrupt(0, NULL, NULL); | ||
956 | 909 | ||
957 | return 0; | 910 | return 0; |
958 | } | 911 | } |
@@ -978,24 +931,24 @@ static int __devinit i8042_create_kbd_port(void) | |||
978 | 931 | ||
979 | serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; | 932 | serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; |
980 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; | 933 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; |
981 | serio->open = i8042_open; | ||
982 | serio->close = i8042_close; | ||
983 | serio->start = i8042_start; | 934 | serio->start = i8042_start; |
984 | serio->stop = i8042_stop; | 935 | serio->stop = i8042_stop; |
985 | serio->port_data = port; | 936 | serio->port_data = port; |
986 | serio->dev.parent = &i8042_platform_device->dev; | 937 | serio->dev.parent = &i8042_platform_device->dev; |
987 | strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); | 938 | strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); |
988 | strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); | 939 | strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); |
989 | 940 | ||
990 | port->serio = serio; | 941 | port->serio = serio; |
942 | port->irq = I8042_KBD_IRQ; | ||
991 | 943 | ||
992 | return i8042_port_register(port); | 944 | return 0; |
993 | } | 945 | } |
994 | 946 | ||
995 | static int __devinit i8042_create_aux_port(void) | 947 | static int __devinit i8042_create_aux_port(int idx) |
996 | { | 948 | { |
997 | struct serio *serio; | 949 | struct serio *serio; |
998 | struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; | 950 | int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; |
951 | struct i8042_port *port = &i8042_ports[port_no]; | ||
999 | 952 | ||
1000 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | 953 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
1001 | if (!serio) | 954 | if (!serio) |
@@ -1003,111 +956,191 @@ static int __devinit i8042_create_aux_port(void) | |||
1003 | 956 | ||
1004 | serio->id.type = SERIO_8042; | 957 | serio->id.type = SERIO_8042; |
1005 | serio->write = i8042_aux_write; | 958 | serio->write = i8042_aux_write; |
1006 | serio->open = i8042_open; | ||
1007 | serio->close = i8042_close; | ||
1008 | serio->start = i8042_start; | 959 | serio->start = i8042_start; |
1009 | serio->stop = i8042_stop; | 960 | serio->stop = i8042_stop; |
1010 | serio->port_data = port; | 961 | serio->port_data = port; |
1011 | serio->dev.parent = &i8042_platform_device->dev; | 962 | serio->dev.parent = &i8042_platform_device->dev; |
1012 | strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); | 963 | if (idx < 0) { |
1013 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | 964 | strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); |
965 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | ||
966 | } else { | ||
967 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); | ||
968 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); | ||
969 | } | ||
1014 | 970 | ||
1015 | port->serio = serio; | 971 | port->serio = serio; |
972 | port->mux = idx; | ||
973 | port->irq = I8042_AUX_IRQ; | ||
1016 | 974 | ||
1017 | return i8042_port_register(port); | 975 | return 0; |
1018 | } | 976 | } |
1019 | 977 | ||
1020 | static int __devinit i8042_create_mux_port(int index) | 978 | static void __devinit i8042_free_kbd_port(void) |
1021 | { | 979 | { |
1022 | struct serio *serio; | 980 | kfree(i8042_ports[I8042_KBD_PORT_NO].serio); |
1023 | struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; | 981 | i8042_ports[I8042_KBD_PORT_NO].serio = NULL; |
982 | } | ||
1024 | 983 | ||
1025 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | 984 | static void __devinit i8042_free_aux_ports(void) |
1026 | if (!serio) | 985 | { |
1027 | return -ENOMEM; | 986 | int i; |
1028 | 987 | ||
1029 | serio->id.type = SERIO_8042; | 988 | for (i = I8042_AUX_PORT_NO; i < I8042_NUM_PORTS; i++) { |
1030 | serio->write = i8042_aux_write; | 989 | kfree(i8042_ports[i].serio); |
1031 | serio->open = i8042_open; | 990 | i8042_ports[i].serio = NULL; |
1032 | serio->close = i8042_close; | 991 | } |
1033 | serio->start = i8042_start; | 992 | } |
1034 | serio->stop = i8042_stop; | ||
1035 | serio->port_data = port; | ||
1036 | serio->dev.parent = &i8042_platform_device->dev; | ||
1037 | snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); | ||
1038 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); | ||
1039 | 993 | ||
1040 | *port = i8042_ports[I8042_AUX_PORT_NO]; | 994 | static void __devinit i8042_register_ports(void) |
1041 | port->exists = 0; | 995 | { |
1042 | snprintf(port->name, sizeof(port->name), "AUX%d", index); | 996 | int i; |
1043 | port->mux = index; | ||
1044 | port->serio = serio; | ||
1045 | 997 | ||
1046 | return i8042_port_register(port); | 998 | for (i = 0; i < I8042_NUM_PORTS; i++) { |
999 | if (i8042_ports[i].serio) { | ||
1000 | printk(KERN_INFO "serio: %s at %#lx,%#lx irq %d\n", | ||
1001 | i8042_ports[i].serio->name, | ||
1002 | (unsigned long) I8042_DATA_REG, | ||
1003 | (unsigned long) I8042_COMMAND_REG, | ||
1004 | i8042_ports[i].irq); | ||
1005 | serio_register_port(i8042_ports[i].serio); | ||
1006 | } | ||
1007 | } | ||
1047 | } | 1008 | } |
1048 | 1009 | ||
1049 | static int __devinit i8042_probe(struct platform_device *dev) | 1010 | static void __devinit i8042_unregister_ports(void) |
1050 | { | 1011 | { |
1051 | int i, have_ports = 0; | 1012 | int i; |
1052 | int err; | ||
1053 | 1013 | ||
1054 | init_timer(&i8042_timer); | 1014 | for (i = 0; i < I8042_NUM_PORTS; i++) { |
1055 | i8042_timer.function = i8042_timer_func; | 1015 | if (i8042_ports[i].serio) { |
1016 | serio_unregister_port(i8042_ports[i].serio); | ||
1017 | i8042_ports[i].serio = NULL; | ||
1018 | } | ||
1019 | } | ||
1020 | } | ||
1021 | |||
1022 | static void i8042_free_irqs(void) | ||
1023 | { | ||
1024 | if (i8042_aux_irq_registered) | ||
1025 | free_irq(I8042_AUX_IRQ, i8042_platform_device); | ||
1026 | if (i8042_kbd_irq_registered) | ||
1027 | free_irq(I8042_KBD_IRQ, i8042_platform_device); | ||
1028 | |||
1029 | i8042_aux_irq_registered = i8042_kbd_irq_registered = 0; | ||
1030 | } | ||
1031 | |||
1032 | static int __devinit i8042_setup_aux(void) | ||
1033 | { | ||
1034 | int (*aux_enable)(void); | ||
1035 | int error; | ||
1036 | int i; | ||
1056 | 1037 | ||
1057 | if (i8042_controller_init()) | 1038 | if (i8042_check_aux()) |
1058 | return -ENODEV; | 1039 | return -ENODEV; |
1059 | 1040 | ||
1060 | if (!i8042_noaux && !i8042_check_aux()) { | 1041 | if (i8042_nomux || i8042_check_mux()) { |
1061 | if (!i8042_nomux && !i8042_check_mux()) { | 1042 | error = i8042_create_aux_port(-1); |
1062 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { | 1043 | if (error) |
1063 | err = i8042_create_mux_port(i); | 1044 | goto err_free_ports; |
1064 | if (err) | 1045 | aux_enable = i8042_enable_aux_port; |
1065 | goto err_unregister_ports; | 1046 | } else { |
1066 | } | 1047 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { |
1067 | } else { | 1048 | error = i8042_create_aux_port(i); |
1068 | err = i8042_create_aux_port(); | 1049 | if (error) |
1069 | if (err) | 1050 | goto err_free_ports; |
1070 | goto err_unregister_ports; | ||
1071 | } | 1051 | } |
1072 | have_ports = 1; | 1052 | aux_enable = i8042_enable_mux_ports; |
1073 | } | 1053 | } |
1074 | 1054 | ||
1075 | if (!i8042_nokbd) { | 1055 | error = request_irq(I8042_AUX_IRQ, i8042_interrupt, IRQF_SHARED, |
1076 | err = i8042_create_kbd_port(); | 1056 | "i8042", i8042_platform_device); |
1077 | if (err) | 1057 | if (error) |
1078 | goto err_unregister_ports; | 1058 | goto err_free_ports; |
1079 | have_ports = 1; | ||
1080 | } | ||
1081 | 1059 | ||
1082 | if (!have_ports) { | 1060 | if (aux_enable()) |
1083 | err = -ENODEV; | 1061 | goto err_free_irq; |
1084 | goto err_controller_cleanup; | ||
1085 | } | ||
1086 | 1062 | ||
1087 | mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); | 1063 | i8042_aux_irq_registered = 1; |
1088 | return 0; | 1064 | return 0; |
1089 | 1065 | ||
1090 | err_unregister_ports: | 1066 | err_free_irq: |
1091 | for (i = 0; i < I8042_NUM_PORTS; i++) | 1067 | free_irq(I8042_AUX_IRQ, i8042_platform_device); |
1092 | if (i8042_ports[i].serio) | 1068 | err_free_ports: |
1093 | serio_unregister_port(i8042_ports[i].serio); | 1069 | i8042_free_aux_ports(); |
1094 | err_controller_cleanup: | 1070 | return error; |
1095 | i8042_controller_cleanup(); | 1071 | } |
1096 | 1072 | ||
1097 | return err; | 1073 | static int __devinit i8042_setup_kbd(void) |
1074 | { | ||
1075 | int error; | ||
1076 | |||
1077 | error = i8042_create_kbd_port(); | ||
1078 | if (error) | ||
1079 | return error; | ||
1080 | |||
1081 | error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED, | ||
1082 | "i8042", i8042_platform_device); | ||
1083 | if (error) | ||
1084 | goto err_free_port; | ||
1085 | |||
1086 | error = i8042_enable_kbd_port(); | ||
1087 | if (error) | ||
1088 | goto err_free_irq; | ||
1089 | |||
1090 | i8042_kbd_irq_registered = 1; | ||
1091 | return 0; | ||
1092 | |||
1093 | err_free_irq: | ||
1094 | free_irq(I8042_KBD_IRQ, i8042_platform_device); | ||
1095 | err_free_port: | ||
1096 | i8042_free_kbd_port(); | ||
1097 | return error; | ||
1098 | } | 1098 | } |
1099 | 1099 | ||
1100 | static int __devexit i8042_remove(struct platform_device *dev) | 1100 | static int __devinit i8042_probe(struct platform_device *dev) |
1101 | { | 1101 | { |
1102 | int i; | 1102 | int error; |
1103 | 1103 | ||
1104 | i8042_controller_cleanup(); | 1104 | error = i8042_controller_selftest(); |
1105 | if (error) | ||
1106 | return error; | ||
1105 | 1107 | ||
1106 | for (i = 0; i < I8042_NUM_PORTS; i++) | 1108 | error = i8042_controller_init(); |
1107 | if (i8042_ports[i].exists) | 1109 | if (error) |
1108 | serio_unregister_port(i8042_ports[i].serio); | 1110 | return error; |
1111 | |||
1112 | if (!i8042_noaux) { | ||
1113 | error = i8042_setup_aux(); | ||
1114 | if (error && error != -ENODEV && error != -EBUSY) | ||
1115 | goto out_fail; | ||
1116 | } | ||
1117 | |||
1118 | if (!i8042_nokbd) { | ||
1119 | error = i8042_setup_kbd(); | ||
1120 | if (error) | ||
1121 | goto out_fail; | ||
1122 | } | ||
1109 | 1123 | ||
1110 | del_timer_sync(&i8042_timer); | 1124 | /* |
1125 | * Ok, everything is ready, let's register all serio ports | ||
1126 | */ | ||
1127 | i8042_register_ports(); | ||
1128 | |||
1129 | return 0; | ||
1130 | |||
1131 | out_fail: | ||
1132 | i8042_free_aux_ports(); /* in case KBD failed but AUX not */ | ||
1133 | i8042_free_irqs(); | ||
1134 | i8042_controller_reset(); | ||
1135 | |||
1136 | return error; | ||
1137 | } | ||
1138 | |||
1139 | static int __devexit i8042_remove(struct platform_device *dev) | ||
1140 | { | ||
1141 | i8042_unregister_ports(); | ||
1142 | i8042_free_irqs(); | ||
1143 | i8042_controller_reset(); | ||
1111 | 1144 | ||
1112 | return 0; | 1145 | return 0; |
1113 | } | 1146 | } |
@@ -1134,8 +1167,9 @@ static int __init i8042_init(void) | |||
1134 | if (err) | 1167 | if (err) |
1135 | return err; | 1168 | return err; |
1136 | 1169 | ||
1137 | i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ; | 1170 | err = i8042_controller_check(); |
1138 | i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; | 1171 | if (err) |
1172 | goto err_platform_exit; | ||
1139 | 1173 | ||
1140 | err = platform_driver_register(&i8042_driver); | 1174 | err = platform_driver_register(&i8042_driver); |
1141 | if (err) | 1175 | if (err) |
@@ -1151,6 +1185,8 @@ static int __init i8042_init(void) | |||
1151 | if (err) | 1185 | if (err) |
1152 | goto err_free_device; | 1186 | goto err_free_device; |
1153 | 1187 | ||
1188 | panic_blink = i8042_panic_blink; | ||
1189 | |||
1154 | return 0; | 1190 | return 0; |
1155 | 1191 | ||
1156 | err_free_device: | 1192 | err_free_device: |
@@ -1167,7 +1203,6 @@ static void __exit i8042_exit(void) | |||
1167 | { | 1203 | { |
1168 | platform_device_unregister(i8042_platform_device); | 1204 | platform_device_unregister(i8042_platform_device); |
1169 | platform_driver_unregister(&i8042_driver); | 1205 | platform_driver_unregister(&i8042_driver); |
1170 | |||
1171 | i8042_platform_exit(); | 1206 | i8042_platform_exit(); |
1172 | 1207 | ||
1173 | panic_blink = NULL; | 1208 | panic_blink = NULL; |
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h index af526ab9ec04..b3eb7a72d961 100644 --- a/drivers/input/serio/i8042.h +++ b/drivers/input/serio/i8042.h | |||
@@ -37,15 +37,6 @@ | |||
37 | #define I8042_CTL_TIMEOUT 10000 | 37 | #define I8042_CTL_TIMEOUT 10000 |
38 | 38 | ||
39 | /* | 39 | /* |
40 | * When the device isn't opened and it's interrupts aren't used, we poll it at | ||
41 | * regular intervals to see if any characters arrived. If yes, we can start | ||
42 | * probing for any mouse / keyboard connected. This is the period of the | ||
43 | * polling. | ||
44 | */ | ||
45 | |||
46 | #define I8042_POLL_PERIOD HZ/20 | ||
47 | |||
48 | /* | ||
49 | * Status register bits. | 40 | * Status register bits. |
50 | */ | 41 | */ |
51 | 42 | ||
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index ed202f2f251a..dcb16b5cbec0 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
@@ -27,15 +27,6 @@ MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); | |||
27 | MODULE_DESCRIPTION("PS/2 driver library"); | 27 | MODULE_DESCRIPTION("PS/2 driver library"); |
28 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
29 | 29 | ||
30 | EXPORT_SYMBOL(ps2_init); | ||
31 | EXPORT_SYMBOL(ps2_sendbyte); | ||
32 | EXPORT_SYMBOL(ps2_drain); | ||
33 | EXPORT_SYMBOL(ps2_command); | ||
34 | EXPORT_SYMBOL(ps2_schedule_command); | ||
35 | EXPORT_SYMBOL(ps2_handle_ack); | ||
36 | EXPORT_SYMBOL(ps2_handle_response); | ||
37 | EXPORT_SYMBOL(ps2_cmd_aborted); | ||
38 | |||
39 | /* Work structure to schedule execution of a command */ | 30 | /* Work structure to schedule execution of a command */ |
40 | struct ps2work { | 31 | struct ps2work { |
41 | struct work_struct work; | 32 | struct work_struct work; |
@@ -71,6 +62,7 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) | |||
71 | 62 | ||
72 | return -ps2dev->nak; | 63 | return -ps2dev->nak; |
73 | } | 64 | } |
65 | EXPORT_SYMBOL(ps2_sendbyte); | ||
74 | 66 | ||
75 | /* | 67 | /* |
76 | * ps2_drain() waits for device to transmit requested number of bytes | 68 | * ps2_drain() waits for device to transmit requested number of bytes |
@@ -96,15 +88,16 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) | |||
96 | msecs_to_jiffies(timeout)); | 88 | msecs_to_jiffies(timeout)); |
97 | mutex_unlock(&ps2dev->cmd_mutex); | 89 | mutex_unlock(&ps2dev->cmd_mutex); |
98 | } | 90 | } |
91 | EXPORT_SYMBOL(ps2_drain); | ||
99 | 92 | ||
100 | /* | 93 | /* |
101 | * ps2_is_keyboard_id() checks received ID byte against the list of | 94 | * ps2_is_keyboard_id() checks received ID byte against the list of |
102 | * known keyboard IDs. | 95 | * known keyboard IDs. |
103 | */ | 96 | */ |
104 | 97 | ||
105 | static inline int ps2_is_keyboard_id(char id_byte) | 98 | int ps2_is_keyboard_id(char id_byte) |
106 | { | 99 | { |
107 | static char keyboard_ids[] = { | 100 | const static char keyboard_ids[] = { |
108 | 0xab, /* Regular keyboards */ | 101 | 0xab, /* Regular keyboards */ |
109 | 0xac, /* NCD Sun keyboard */ | 102 | 0xac, /* NCD Sun keyboard */ |
110 | 0x2b, /* Trust keyboard, translated */ | 103 | 0x2b, /* Trust keyboard, translated */ |
@@ -115,6 +108,7 @@ static inline int ps2_is_keyboard_id(char id_byte) | |||
115 | 108 | ||
116 | return memchr(keyboard_ids, id_byte, sizeof(keyboard_ids)) != NULL; | 109 | return memchr(keyboard_ids, id_byte, sizeof(keyboard_ids)) != NULL; |
117 | } | 110 | } |
111 | EXPORT_SYMBOL(ps2_is_keyboard_id); | ||
118 | 112 | ||
119 | /* | 113 | /* |
120 | * ps2_adjust_timeout() is called after receiving 1st byte of command | 114 | * ps2_adjust_timeout() is called after receiving 1st byte of command |
@@ -139,6 +133,19 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout) | |||
139 | 133 | ||
140 | case PS2_CMD_GETID: | 134 | case PS2_CMD_GETID: |
141 | /* | 135 | /* |
136 | * Microsoft Natural Elite keyboard responds to | ||
137 | * the GET ID command as it were a mouse, with | ||
138 | * a single byte. Fail the command so atkbd will | ||
139 | * use alternative probe to detect it. | ||
140 | */ | ||
141 | if (ps2dev->cmdbuf[1] == 0xaa) { | ||
142 | serio_pause_rx(ps2dev->serio); | ||
143 | ps2dev->flags = 0; | ||
144 | serio_continue_rx(ps2dev->serio); | ||
145 | timeout = 0; | ||
146 | } | ||
147 | |||
148 | /* | ||
142 | * If device behind the port is not a keyboard there | 149 | * If device behind the port is not a keyboard there |
143 | * won't be 2nd byte of ID response. | 150 | * won't be 2nd byte of ID response. |
144 | */ | 151 | */ |
@@ -237,6 +244,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
237 | mutex_unlock(&ps2dev->cmd_mutex); | 244 | mutex_unlock(&ps2dev->cmd_mutex); |
238 | return rc; | 245 | return rc; |
239 | } | 246 | } |
247 | EXPORT_SYMBOL(ps2_command); | ||
240 | 248 | ||
241 | /* | 249 | /* |
242 | * ps2_execute_scheduled_command() sends a command, previously scheduled by | 250 | * ps2_execute_scheduled_command() sends a command, previously scheduled by |
@@ -279,6 +287,7 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman | |||
279 | 287 | ||
280 | return 0; | 288 | return 0; |
281 | } | 289 | } |
290 | EXPORT_SYMBOL(ps2_schedule_command); | ||
282 | 291 | ||
283 | /* | 292 | /* |
284 | * ps2_init() initializes ps2dev structure | 293 | * ps2_init() initializes ps2dev structure |
@@ -290,6 +299,7 @@ void ps2_init(struct ps2dev *ps2dev, struct serio *serio) | |||
290 | init_waitqueue_head(&ps2dev->wait); | 299 | init_waitqueue_head(&ps2dev->wait); |
291 | ps2dev->serio = serio; | 300 | ps2dev->serio = serio; |
292 | } | 301 | } |
302 | EXPORT_SYMBOL(ps2_init); | ||
293 | 303 | ||
294 | /* | 304 | /* |
295 | * ps2_handle_ack() is supposed to be used in interrupt handler | 305 | * ps2_handle_ack() is supposed to be used in interrupt handler |
@@ -335,6 +345,7 @@ int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data) | |||
335 | 345 | ||
336 | return 1; | 346 | return 1; |
337 | } | 347 | } |
348 | EXPORT_SYMBOL(ps2_handle_ack); | ||
338 | 349 | ||
339 | /* | 350 | /* |
340 | * ps2_handle_response() is supposed to be used in interrupt handler | 351 | * ps2_handle_response() is supposed to be used in interrupt handler |
@@ -360,6 +371,7 @@ int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data) | |||
360 | 371 | ||
361 | return 1; | 372 | return 1; |
362 | } | 373 | } |
374 | EXPORT_SYMBOL(ps2_handle_response); | ||
363 | 375 | ||
364 | void ps2_cmd_aborted(struct ps2dev *ps2dev) | 376 | void ps2_cmd_aborted(struct ps2dev *ps2dev) |
365 | { | 377 | { |
@@ -371,4 +383,4 @@ void ps2_cmd_aborted(struct ps2dev *ps2dev) | |||
371 | 383 | ||
372 | ps2dev->flags = 0; | 384 | ps2dev->flags = 0; |
373 | } | 385 | } |
374 | 386 | EXPORT_SYMBOL(ps2_cmd_aborted); | |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index b1b14f8d4dd6..9418bbe47072 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -108,4 +108,40 @@ config TOUCHSCREEN_HP600 | |||
108 | To compile this driver as a module, choose M here: the | 108 | To compile this driver as a module, choose M here: the |
109 | module will be called hp680_ts_input. | 109 | module will be called hp680_ts_input. |
110 | 110 | ||
111 | config TOUCHSCREEN_PENMOUNT | ||
112 | tristate "Penmount serial touchscreen" | ||
113 | select SERIO | ||
114 | help | ||
115 | Say Y here if you have a Penmount serial touchscreen connected to | ||
116 | your system. | ||
117 | |||
118 | If unsure, say N. | ||
119 | |||
120 | To compile this driver as a module, choose M here: the | ||
121 | module will be called penmount. | ||
122 | |||
123 | config TOUCHSCREEN_TOUCHRIGHT | ||
124 | tristate "Touchright serial touchscreen" | ||
125 | select SERIO | ||
126 | help | ||
127 | Say Y here if you have a Touchright serial touchscreen connected to | ||
128 | your system. | ||
129 | |||
130 | If unsure, say N. | ||
131 | |||
132 | To compile this driver as a module, choose M here: the | ||
133 | module will be called touchright. | ||
134 | |||
135 | config TOUCHSCREEN_TOUCHWIN | ||
136 | tristate "Touchwin serial touchscreen" | ||
137 | select SERIO | ||
138 | help | ||
139 | Say Y here if you have a Touchwin serial touchscreen connected to | ||
140 | your system. | ||
141 | |||
142 | If unsure, say N. | ||
143 | |||
144 | To compile this driver as a module, choose M here: the | ||
145 | module will be called touchwin. | ||
146 | |||
111 | endif | 147 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 5e5557c43121..1abb8f10d608 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -12,3 +12,6 @@ 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_PENMOUNT) += penmount.o | ||
16 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | ||
17 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | ||
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index c86a2eb310fd..ab565335ee44 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/input.h> | 23 | #include <linux/input.h> |
24 | #include <linux/serio.h> | 24 | #include <linux/serio.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/ctype.h> | ||
26 | 27 | ||
27 | #define DRIVER_DESC "Elo serial touchscreen driver" | 28 | #define DRIVER_DESC "Elo serial touchscreen driver" |
28 | 29 | ||
@@ -34,7 +35,19 @@ MODULE_LICENSE("GPL"); | |||
34 | * Definitions & global arrays. | 35 | * Definitions & global arrays. |
35 | */ | 36 | */ |
36 | 37 | ||
37 | #define ELO_MAX_LENGTH 10 | 38 | #define ELO_MAX_LENGTH 10 |
39 | |||
40 | #define ELO10_PACKET_LEN 8 | ||
41 | #define ELO10_TOUCH 0x03 | ||
42 | #define ELO10_PRESSURE 0x80 | ||
43 | |||
44 | #define ELO10_LEAD_BYTE 'U' | ||
45 | |||
46 | #define ELO10_ID_CMD 'i' | ||
47 | |||
48 | #define ELO10_TOUCH_PACKET 'T' | ||
49 | #define ELO10_ACK_PACKET 'A' | ||
50 | #define ELI10_ID_PACKET 'I' | ||
38 | 51 | ||
39 | /* | 52 | /* |
40 | * Per-touchscreen data. | 53 | * Per-touchscreen data. |
@@ -43,51 +56,67 @@ MODULE_LICENSE("GPL"); | |||
43 | struct elo { | 56 | struct elo { |
44 | struct input_dev *dev; | 57 | struct input_dev *dev; |
45 | struct serio *serio; | 58 | struct serio *serio; |
59 | struct mutex cmd_mutex; | ||
60 | struct completion cmd_done; | ||
46 | int id; | 61 | int id; |
47 | int idx; | 62 | int idx; |
63 | unsigned char expected_packet; | ||
48 | unsigned char csum; | 64 | unsigned char csum; |
49 | unsigned char data[ELO_MAX_LENGTH]; | 65 | unsigned char data[ELO_MAX_LENGTH]; |
66 | unsigned char response[ELO10_PACKET_LEN]; | ||
50 | char phys[32]; | 67 | char phys[32]; |
51 | }; | 68 | }; |
52 | 69 | ||
53 | static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_regs *regs) | 70 | static void elo_process_data_10(struct elo *elo, unsigned char data, struct pt_regs *regs) |
54 | { | 71 | { |
55 | struct input_dev *dev = elo->dev; | 72 | struct input_dev *dev = elo->dev; |
56 | 73 | ||
57 | elo->csum += elo->data[elo->idx] = data; | 74 | elo->data[elo->idx] = data; |
58 | |||
59 | switch (elo->idx++) { | 75 | switch (elo->idx++) { |
60 | |||
61 | case 0: | 76 | case 0: |
62 | if (data != 'U') { | 77 | elo->csum = 0xaa; |
78 | if (data != ELO10_LEAD_BYTE) { | ||
79 | pr_debug("elo: unsynchronized data: 0x%02x\n", data); | ||
63 | elo->idx = 0; | 80 | elo->idx = 0; |
64 | elo->csum = 0; | ||
65 | } | ||
66 | break; | ||
67 | |||
68 | case 1: | ||
69 | if (data != 'T') { | ||
70 | elo->idx = 0; | ||
71 | elo->csum = 0; | ||
72 | } | 81 | } |
73 | break; | 82 | break; |
74 | 83 | ||
75 | case 9: | 84 | case 9: |
76 | if (elo->csum) { | 85 | elo->idx = 0; |
86 | if (data != elo->csum) { | ||
87 | pr_debug("elo: bad checksum: 0x%02x, expected 0x%02x\n", | ||
88 | data, elo->csum); | ||
89 | break; | ||
90 | } | ||
91 | if (elo->data[1] != elo->expected_packet) { | ||
92 | if (elo->data[1] != ELO10_TOUCH_PACKET) | ||
93 | pr_debug("elo: unexpected packet: 0x%02x\n", | ||
94 | elo->data[1]); | ||
95 | break; | ||
96 | } | ||
97 | if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) { | ||
77 | input_regs(dev, regs); | 98 | input_regs(dev, regs); |
78 | input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); | 99 | input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); |
79 | input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); | 100 | input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); |
80 | input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]); | 101 | if (elo->data[2] & ELO10_PRESSURE) |
81 | input_report_key(dev, BTN_TOUCH, elo->data[8] || elo->data[7]); | 102 | input_report_abs(dev, ABS_PRESSURE, |
103 | (elo->data[8] << 8) | elo->data[7]); | ||
104 | input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH); | ||
82 | input_sync(dev); | 105 | input_sync(dev); |
106 | } else if (elo->data[1] == ELO10_ACK_PACKET) { | ||
107 | if (elo->data[2] == '0') | ||
108 | elo->expected_packet = ELO10_TOUCH_PACKET; | ||
109 | complete(&elo->cmd_done); | ||
110 | } else { | ||
111 | memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN); | ||
112 | elo->expected_packet = ELO10_ACK_PACKET; | ||
83 | } | 113 | } |
84 | elo->idx = 0; | ||
85 | elo->csum = 0; | ||
86 | break; | 114 | break; |
87 | } | 115 | } |
116 | elo->csum += data; | ||
88 | } | 117 | } |
89 | 118 | ||
90 | static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_regs *regs) | 119 | static void elo_process_data_6(struct elo *elo, unsigned char data, struct pt_regs *regs) |
91 | { | 120 | { |
92 | struct input_dev *dev = elo->dev; | 121 | struct input_dev *dev = elo->dev; |
93 | 122 | ||
@@ -135,7 +164,7 @@ static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_re | |||
135 | } | 164 | } |
136 | } | 165 | } |
137 | 166 | ||
138 | static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_regs *regs) | 167 | static void elo_process_data_3(struct elo *elo, unsigned char data, struct pt_regs *regs) |
139 | { | 168 | { |
140 | struct input_dev *dev = elo->dev; | 169 | struct input_dev *dev = elo->dev; |
141 | 170 | ||
@@ -161,7 +190,7 @@ static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_re | |||
161 | static irqreturn_t elo_interrupt(struct serio *serio, | 190 | static irqreturn_t elo_interrupt(struct serio *serio, |
162 | unsigned char data, unsigned int flags, struct pt_regs *regs) | 191 | unsigned char data, unsigned int flags, struct pt_regs *regs) |
163 | { | 192 | { |
164 | struct elo* elo = serio_get_drvdata(serio); | 193 | struct elo *elo = serio_get_drvdata(serio); |
165 | 194 | ||
166 | switch(elo->id) { | 195 | switch(elo->id) { |
167 | case 0: | 196 | case 0: |
@@ -181,17 +210,81 @@ static irqreturn_t elo_interrupt(struct serio *serio, | |||
181 | return IRQ_HANDLED; | 210 | return IRQ_HANDLED; |
182 | } | 211 | } |
183 | 212 | ||
213 | static int elo_command_10(struct elo *elo, unsigned char *packet) | ||
214 | { | ||
215 | int rc = -1; | ||
216 | int i; | ||
217 | unsigned char csum = 0xaa + ELO10_LEAD_BYTE; | ||
218 | |||
219 | mutex_lock(&elo->cmd_mutex); | ||
220 | |||
221 | serio_pause_rx(elo->serio); | ||
222 | elo->expected_packet = toupper(packet[0]); | ||
223 | init_completion(&elo->cmd_done); | ||
224 | serio_continue_rx(elo->serio); | ||
225 | |||
226 | if (serio_write(elo->serio, ELO10_LEAD_BYTE)) | ||
227 | goto out; | ||
228 | |||
229 | for (i = 0; i < ELO10_PACKET_LEN; i++) { | ||
230 | csum += packet[i]; | ||
231 | if (serio_write(elo->serio, packet[i])) | ||
232 | goto out; | ||
233 | } | ||
234 | |||
235 | if (serio_write(elo->serio, csum)) | ||
236 | goto out; | ||
237 | |||
238 | wait_for_completion_timeout(&elo->cmd_done, HZ); | ||
239 | |||
240 | if (elo->expected_packet == ELO10_TOUCH_PACKET) { | ||
241 | /* We are back in reporting mode, the command was ACKed */ | ||
242 | memcpy(packet, elo->response, ELO10_PACKET_LEN); | ||
243 | rc = 0; | ||
244 | } | ||
245 | |||
246 | out: | ||
247 | mutex_unlock(&elo->cmd_mutex); | ||
248 | return rc; | ||
249 | } | ||
250 | |||
251 | static int elo_setup_10(struct elo *elo) | ||
252 | { | ||
253 | static const char *elo_types[] = { "Accu", "Dura", "Intelli", "Carroll" }; | ||
254 | struct input_dev *dev = elo->dev; | ||
255 | unsigned char packet[ELO10_PACKET_LEN] = { ELO10_ID_CMD }; | ||
256 | |||
257 | if (elo_command_10(elo, packet)) | ||
258 | return -1; | ||
259 | |||
260 | dev->id.version = (packet[5] << 8) | packet[4]; | ||
261 | |||
262 | input_set_abs_params(dev, ABS_X, 96, 4000, 0, 0); | ||
263 | input_set_abs_params(dev, ABS_Y, 96, 4000, 0, 0); | ||
264 | if (packet[3] & ELO10_PRESSURE) | ||
265 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | ||
266 | |||
267 | printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, " | ||
268 | "features: %x02x, controller: 0x%02x\n", | ||
269 | elo_types[(packet[1] -'0') & 0x03], | ||
270 | packet[5], packet[4], packet[3], packet[7]); | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
184 | /* | 275 | /* |
185 | * elo_disconnect() is the opposite of elo_connect() | 276 | * elo_disconnect() is the opposite of elo_connect() |
186 | */ | 277 | */ |
187 | 278 | ||
188 | static void elo_disconnect(struct serio *serio) | 279 | static void elo_disconnect(struct serio *serio) |
189 | { | 280 | { |
190 | struct elo* elo = serio_get_drvdata(serio); | 281 | struct elo *elo = serio_get_drvdata(serio); |
191 | 282 | ||
283 | input_get_device(elo->dev); | ||
192 | input_unregister_device(elo->dev); | 284 | input_unregister_device(elo->dev); |
193 | serio_close(serio); | 285 | serio_close(serio); |
194 | serio_set_drvdata(serio, NULL); | 286 | serio_set_drvdata(serio, NULL); |
287 | input_put_device(elo->dev); | ||
195 | kfree(elo); | 288 | kfree(elo); |
196 | } | 289 | } |
197 | 290 | ||
@@ -211,12 +304,15 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) | |||
211 | input_dev = input_allocate_device(); | 304 | input_dev = input_allocate_device(); |
212 | if (!elo || !input_dev) { | 305 | if (!elo || !input_dev) { |
213 | err = -ENOMEM; | 306 | err = -ENOMEM; |
214 | goto fail; | 307 | goto fail1; |
215 | } | 308 | } |
216 | 309 | ||
217 | elo->serio = serio; | 310 | elo->serio = serio; |
218 | elo->id = serio->id.id; | 311 | elo->id = serio->id.id; |
219 | elo->dev = input_dev; | 312 | elo->dev = input_dev; |
313 | elo->expected_packet = ELO10_TOUCH_PACKET; | ||
314 | mutex_init(&elo->cmd_mutex); | ||
315 | init_completion(&elo->cmd_done); | ||
220 | snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys); | 316 | snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys); |
221 | 317 | ||
222 | input_dev->private = elo; | 318 | input_dev->private = elo; |
@@ -231,12 +327,17 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) | |||
231 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | 327 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
232 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | 328 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); |
233 | 329 | ||
330 | serio_set_drvdata(serio, elo); | ||
331 | err = serio_open(serio, drv); | ||
332 | if (err) | ||
333 | goto fail2; | ||
334 | |||
234 | switch (elo->id) { | 335 | switch (elo->id) { |
235 | 336 | ||
236 | case 0: /* 10-byte protocol */ | 337 | case 0: /* 10-byte protocol */ |
237 | input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); | 338 | if (elo_setup_10(elo)) |
238 | input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); | 339 | goto fail3; |
239 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); | 340 | |
240 | break; | 341 | break; |
241 | 342 | ||
242 | case 1: /* 6-byte protocol */ | 343 | case 1: /* 6-byte protocol */ |
@@ -253,17 +354,15 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) | |||
253 | break; | 354 | break; |
254 | } | 355 | } |
255 | 356 | ||
256 | serio_set_drvdata(serio, elo); | 357 | err = input_register_device(elo->dev); |
257 | |||
258 | err = serio_open(serio, drv); | ||
259 | if (err) | 358 | if (err) |
260 | goto fail; | 359 | goto fail3; |
261 | 360 | ||
262 | input_register_device(elo->dev); | ||
263 | return 0; | 361 | return 0; |
264 | 362 | ||
265 | fail: serio_set_drvdata(serio, NULL); | 363 | fail3: serio_close(serio); |
266 | input_free_device(input_dev); | 364 | fail2: serio_set_drvdata(serio, NULL); |
365 | fail1: input_free_device(input_dev); | ||
267 | kfree(elo); | 366 | kfree(elo); |
268 | return err; | 367 | return err; |
269 | } | 368 | } |
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c new file mode 100644 index 000000000000..f7370109d43e --- /dev/null +++ b/drivers/input/touchscreen/penmount.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * Penmount serial touchscreen driver | ||
3 | * | ||
4 | * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com> | ||
5 | * | ||
6 | * Based on ELO driver (drivers/input/touchscreen/elo.c) | ||
7 | * Copyright (c) 2004 Vojtech Pavlik | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License version 2 as published | ||
13 | * by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/errno.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/serio.h> | ||
22 | #include <linux/init.h> | ||
23 | |||
24 | #define DRIVER_DESC "Penmount serial touchscreen driver" | ||
25 | |||
26 | MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>"); | ||
27 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | /* | ||
31 | * Definitions & global arrays. | ||
32 | */ | ||
33 | |||
34 | #define PM_MAX_LENGTH 5 | ||
35 | |||
36 | /* | ||
37 | * Per-touchscreen data. | ||
38 | */ | ||
39 | |||
40 | struct pm { | ||
41 | struct input_dev *dev; | ||
42 | struct serio *serio; | ||
43 | int idx; | ||
44 | unsigned char data[PM_MAX_LENGTH]; | ||
45 | char phys[32]; | ||
46 | }; | ||
47 | |||
48 | static irqreturn_t pm_interrupt(struct serio *serio, | ||
49 | unsigned char data, unsigned int flags, struct pt_regs *regs) | ||
50 | { | ||
51 | struct pm *pm = serio_get_drvdata(serio); | ||
52 | struct input_dev *dev = pm->dev; | ||
53 | |||
54 | pm->data[pm->idx] = data; | ||
55 | |||
56 | if (pm->data[0] & 0x80) { | ||
57 | if (PM_MAX_LENGTH == ++pm->idx) { | ||
58 | input_regs(dev, regs); | ||
59 | input_report_abs(dev, ABS_X, pm->data[2] * 128 + pm->data[1]); | ||
60 | input_report_abs(dev, ABS_Y, pm->data[4] * 128 + pm->data[3]); | ||
61 | input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40)); | ||
62 | input_sync(dev); | ||
63 | pm->idx = 0; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | return IRQ_HANDLED; | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * pm_disconnect() is the opposite of pm_connect() | ||
72 | */ | ||
73 | |||
74 | static void pm_disconnect(struct serio *serio) | ||
75 | { | ||
76 | struct pm *pm = serio_get_drvdata(serio); | ||
77 | |||
78 | input_get_device(pm->dev); | ||
79 | input_unregister_device(pm->dev); | ||
80 | serio_close(serio); | ||
81 | serio_set_drvdata(serio, NULL); | ||
82 | input_put_device(pm->dev); | ||
83 | kfree(pm); | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * pm_connect() is the routine that is called when someone adds a | ||
88 | * new serio device that supports Gunze protocol and registers it as | ||
89 | * an input device. | ||
90 | */ | ||
91 | |||
92 | static int pm_connect(struct serio *serio, struct serio_driver *drv) | ||
93 | { | ||
94 | struct pm *pm; | ||
95 | struct input_dev *input_dev; | ||
96 | int err; | ||
97 | |||
98 | pm = kzalloc(sizeof(struct pm), GFP_KERNEL); | ||
99 | input_dev = input_allocate_device(); | ||
100 | if (!pm || !input_dev) { | ||
101 | err = -ENOMEM; | ||
102 | goto fail1; | ||
103 | } | ||
104 | |||
105 | pm->serio = serio; | ||
106 | pm->dev = input_dev; | ||
107 | snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys); | ||
108 | |||
109 | input_dev->private = pm; | ||
110 | input_dev->name = "Penmount Serial TouchScreen"; | ||
111 | input_dev->phys = pm->phys; | ||
112 | input_dev->id.bustype = BUS_RS232; | ||
113 | input_dev->id.vendor = SERIO_PENMOUNT; | ||
114 | input_dev->id.product = 0; | ||
115 | input_dev->id.version = 0x0100; | ||
116 | input_dev->cdev.dev = &serio->dev; | ||
117 | |||
118 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
119 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
120 | input_set_abs_params(pm->dev, ABS_X, 0, 0x3ff, 0, 0); | ||
121 | input_set_abs_params(pm->dev, ABS_Y, 0, 0x3ff, 0, 0); | ||
122 | |||
123 | serio_set_drvdata(serio, pm); | ||
124 | |||
125 | err = serio_open(serio, drv); | ||
126 | if (err) | ||
127 | goto fail2; | ||
128 | |||
129 | err = input_register_device(pm->dev); | ||
130 | if (err) | ||
131 | goto fail3; | ||
132 | |||
133 | return 0; | ||
134 | |||
135 | fail3: serio_close(serio); | ||
136 | fail2: serio_set_drvdata(serio, NULL); | ||
137 | fail1: input_free_device(input_dev); | ||
138 | kfree(pm); | ||
139 | return err; | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * The serio driver structure. | ||
144 | */ | ||
145 | |||
146 | static struct serio_device_id pm_serio_ids[] = { | ||
147 | { | ||
148 | .type = SERIO_RS232, | ||
149 | .proto = SERIO_PENMOUNT, | ||
150 | .id = SERIO_ANY, | ||
151 | .extra = SERIO_ANY, | ||
152 | }, | ||
153 | { 0 } | ||
154 | }; | ||
155 | |||
156 | MODULE_DEVICE_TABLE(serio, pm_serio_ids); | ||
157 | |||
158 | static struct serio_driver pm_drv = { | ||
159 | .driver = { | ||
160 | .name = "penmountlpc", | ||
161 | }, | ||
162 | .description = DRIVER_DESC, | ||
163 | .id_table = pm_serio_ids, | ||
164 | .interrupt = pm_interrupt, | ||
165 | .connect = pm_connect, | ||
166 | .disconnect = pm_disconnect, | ||
167 | }; | ||
168 | |||
169 | /* | ||
170 | * The functions for inserting/removing us as a module. | ||
171 | */ | ||
172 | |||
173 | static int __init pm_init(void) | ||
174 | { | ||
175 | serio_register_driver(&pm_drv); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static void __exit pm_exit(void) | ||
180 | { | ||
181 | serio_unregister_driver(&pm_drv); | ||
182 | } | ||
183 | |||
184 | module_init(pm_init); | ||
185 | module_exit(pm_exit); | ||
diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c new file mode 100644 index 000000000000..1c89fa538651 --- /dev/null +++ b/drivers/input/touchscreen/touchright.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * Touchright serial touchscreen driver | ||
3 | * | ||
4 | * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com> | ||
5 | * | ||
6 | * Based on MicroTouch driver (drivers/input/touchscreen/mtouch.c) | ||
7 | * Copyright (c) 2004 Vojtech Pavlik | ||
8 | * and Dan Streetman <ddstreet@ieee.org> | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License version 2 as published | ||
14 | * by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/errno.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/serio.h> | ||
23 | #include <linux/init.h> | ||
24 | |||
25 | #define DRIVER_DESC "Touchright serial touchscreen driver" | ||
26 | |||
27 | MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>"); | ||
28 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
29 | MODULE_LICENSE("GPL"); | ||
30 | |||
31 | /* | ||
32 | * Definitions & global arrays. | ||
33 | */ | ||
34 | |||
35 | #define TR_FORMAT_TOUCH_BIT 0x01 | ||
36 | #define TR_FORMAT_STATUS_BYTE 0x40 | ||
37 | #define TR_FORMAT_STATUS_MASK ~TR_FORMAT_TOUCH_BIT | ||
38 | |||
39 | #define TR_LENGTH 5 | ||
40 | |||
41 | #define TR_MIN_XC 0 | ||
42 | #define TR_MAX_XC 0x1ff | ||
43 | #define TR_MIN_YC 0 | ||
44 | #define TR_MAX_YC 0x1ff | ||
45 | |||
46 | /* | ||
47 | * Per-touchscreen data. | ||
48 | */ | ||
49 | |||
50 | struct tr { | ||
51 | struct input_dev *dev; | ||
52 | struct serio *serio; | ||
53 | int idx; | ||
54 | unsigned char data[TR_LENGTH]; | ||
55 | char phys[32]; | ||
56 | }; | ||
57 | |||
58 | static irqreturn_t tr_interrupt(struct serio *serio, | ||
59 | unsigned char data, unsigned int flags, struct pt_regs *regs) | ||
60 | { | ||
61 | struct tr *tr = serio_get_drvdata(serio); | ||
62 | struct input_dev *dev = tr->dev; | ||
63 | |||
64 | tr->data[tr->idx] = data; | ||
65 | |||
66 | if ((tr->data[0] & TR_FORMAT_STATUS_MASK) == TR_FORMAT_STATUS_BYTE) { | ||
67 | if (++tr->idx == TR_LENGTH) { | ||
68 | input_regs(dev, regs); | ||
69 | input_report_abs(dev, ABS_X, | ||
70 | (tr->data[1] << 5) | (tr->data[2] >> 1)); | ||
71 | input_report_abs(dev, ABS_Y, | ||
72 | (tr->data[3] << 5) | (tr->data[4] >> 1)); | ||
73 | input_report_key(dev, BTN_TOUCH, | ||
74 | tr->data[0] & TR_FORMAT_TOUCH_BIT); | ||
75 | input_sync(dev); | ||
76 | tr->idx = 0; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | return IRQ_HANDLED; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * tr_disconnect() is the opposite of tr_connect() | ||
85 | */ | ||
86 | |||
87 | static void tr_disconnect(struct serio *serio) | ||
88 | { | ||
89 | struct tr *tr = serio_get_drvdata(serio); | ||
90 | |||
91 | input_get_device(tr->dev); | ||
92 | input_unregister_device(tr->dev); | ||
93 | serio_close(serio); | ||
94 | serio_set_drvdata(serio, NULL); | ||
95 | input_put_device(tr->dev); | ||
96 | kfree(tr); | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * tr_connect() is the routine that is called when someone adds a | ||
101 | * new serio device that supports the Touchright protocol and registers it as | ||
102 | * an input device. | ||
103 | */ | ||
104 | |||
105 | static int tr_connect(struct serio *serio, struct serio_driver *drv) | ||
106 | { | ||
107 | struct tr *tr; | ||
108 | struct input_dev *input_dev; | ||
109 | int err; | ||
110 | |||
111 | tr = kzalloc(sizeof(struct tr), GFP_KERNEL); | ||
112 | input_dev = input_allocate_device(); | ||
113 | if (!tr || !input_dev) { | ||
114 | err = -ENOMEM; | ||
115 | goto fail1; | ||
116 | } | ||
117 | |||
118 | tr->serio = serio; | ||
119 | tr->dev = input_dev; | ||
120 | snprintf(tr->phys, sizeof(tr->phys), "%s/input0", serio->phys); | ||
121 | |||
122 | input_dev->private = tr; | ||
123 | input_dev->name = "Touchright Serial TouchScreen"; | ||
124 | input_dev->phys = tr->phys; | ||
125 | input_dev->id.bustype = BUS_RS232; | ||
126 | input_dev->id.vendor = SERIO_TOUCHRIGHT; | ||
127 | input_dev->id.product = 0; | ||
128 | input_dev->id.version = 0x0100; | ||
129 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
130 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
131 | input_set_abs_params(tr->dev, ABS_X, TR_MIN_XC, TR_MAX_XC, 0, 0); | ||
132 | input_set_abs_params(tr->dev, ABS_Y, TR_MIN_YC, TR_MAX_YC, 0, 0); | ||
133 | |||
134 | serio_set_drvdata(serio, tr); | ||
135 | |||
136 | err = serio_open(serio, drv); | ||
137 | if (err) | ||
138 | goto fail2; | ||
139 | |||
140 | err = input_register_device(tr->dev); | ||
141 | if (err) | ||
142 | goto fail3; | ||
143 | |||
144 | return 0; | ||
145 | |||
146 | fail3: serio_close(serio); | ||
147 | fail2: serio_set_drvdata(serio, NULL); | ||
148 | fail1: input_free_device(input_dev); | ||
149 | kfree(tr); | ||
150 | return err; | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * The serio driver structure. | ||
155 | */ | ||
156 | |||
157 | static struct serio_device_id tr_serio_ids[] = { | ||
158 | { | ||
159 | .type = SERIO_RS232, | ||
160 | .proto = SERIO_TOUCHRIGHT, | ||
161 | .id = SERIO_ANY, | ||
162 | .extra = SERIO_ANY, | ||
163 | }, | ||
164 | { 0 } | ||
165 | }; | ||
166 | |||
167 | MODULE_DEVICE_TABLE(serio, tr_serio_ids); | ||
168 | |||
169 | static struct serio_driver tr_drv = { | ||
170 | .driver = { | ||
171 | .name = "touchright", | ||
172 | }, | ||
173 | .description = DRIVER_DESC, | ||
174 | .id_table = tr_serio_ids, | ||
175 | .interrupt = tr_interrupt, | ||
176 | .connect = tr_connect, | ||
177 | .disconnect = tr_disconnect, | ||
178 | }; | ||
179 | |||
180 | /* | ||
181 | * The functions for inserting/removing us as a module. | ||
182 | */ | ||
183 | |||
184 | static int __init tr_init(void) | ||
185 | { | ||
186 | serio_register_driver(&tr_drv); | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static void __exit tr_exit(void) | ||
191 | { | ||
192 | serio_unregister_driver(&tr_drv); | ||
193 | } | ||
194 | |||
195 | module_init(tr_init); | ||
196 | module_exit(tr_exit); | ||
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c new file mode 100644 index 000000000000..a7b4c755958e --- /dev/null +++ b/drivers/input/touchscreen/touchwin.c | |||
@@ -0,0 +1,203 @@ | |||
1 | /* | ||
2 | * Touchwindow serial touchscreen driver | ||
3 | * | ||
4 | * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com> | ||
5 | * | ||
6 | * Based on MicroTouch driver (drivers/input/touchscreen/mtouch.c) | ||
7 | * Copyright (c) 2004 Vojtech Pavlik | ||
8 | * and Dan Streetman <ddstreet@ieee.org> | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License version 2 as published | ||
14 | * by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | /* | ||
18 | * 2005/02/19 Rick Koch: | ||
19 | * The Touchwindow I used is made by Edmark Corp. and | ||
20 | * constantly outputs a stream of 0's unless it is touched. | ||
21 | * It then outputs 3 bytes: X, Y, and a copy of Y. | ||
22 | */ | ||
23 | |||
24 | #include <linux/errno.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/input.h> | ||
29 | #include <linux/serio.h> | ||
30 | #include <linux/init.h> | ||
31 | |||
32 | #define DRIVER_DESC "Touchwindow serial touchscreen driver" | ||
33 | |||
34 | MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>"); | ||
35 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
36 | MODULE_LICENSE("GPL"); | ||
37 | |||
38 | /* | ||
39 | * Definitions & global arrays. | ||
40 | */ | ||
41 | |||
42 | #define TW_LENGTH 3 | ||
43 | |||
44 | #define TW_MIN_XC 0 | ||
45 | #define TW_MAX_XC 0xff | ||
46 | #define TW_MIN_YC 0 | ||
47 | #define TW_MAX_YC 0xff | ||
48 | |||
49 | /* | ||
50 | * Per-touchscreen data. | ||
51 | */ | ||
52 | |||
53 | struct tw { | ||
54 | struct input_dev *dev; | ||
55 | struct serio *serio; | ||
56 | int idx; | ||
57 | int touched; | ||
58 | unsigned char data[TW_LENGTH]; | ||
59 | char phys[32]; | ||
60 | }; | ||
61 | |||
62 | static irqreturn_t tw_interrupt(struct serio *serio, | ||
63 | unsigned char data, unsigned int flags, struct pt_regs *regs) | ||
64 | { | ||
65 | struct tw *tw = serio_get_drvdata(serio); | ||
66 | struct input_dev *dev = tw->dev; | ||
67 | |||
68 | if (data) { /* touch */ | ||
69 | tw->touched = 1; | ||
70 | tw->data[tw->idx++] = data; | ||
71 | /* verify length and that the two Y's are the same */ | ||
72 | if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) { | ||
73 | input_regs(dev, regs); | ||
74 | input_report_abs(dev, ABS_X, tw->data[0]); | ||
75 | input_report_abs(dev, ABS_Y, tw->data[1]); | ||
76 | input_report_key(dev, BTN_TOUCH, 1); | ||
77 | input_sync(dev); | ||
78 | tw->idx = 0; | ||
79 | } | ||
80 | } else if (tw->touched) { /* untouch */ | ||
81 | input_report_key(dev, BTN_TOUCH, 0); | ||
82 | input_sync(dev); | ||
83 | tw->idx = 0; | ||
84 | tw->touched = 0; | ||
85 | } | ||
86 | |||
87 | return IRQ_HANDLED; | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * tw_disconnect() is the opposite of tw_connect() | ||
92 | */ | ||
93 | |||
94 | static void tw_disconnect(struct serio *serio) | ||
95 | { | ||
96 | struct tw *tw = serio_get_drvdata(serio); | ||
97 | |||
98 | input_get_device(tw->dev); | ||
99 | input_unregister_device(tw->dev); | ||
100 | serio_close(serio); | ||
101 | serio_set_drvdata(serio, NULL); | ||
102 | input_put_device(tw->dev); | ||
103 | kfree(tw); | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * tw_connect() is the routine that is called when someone adds a | ||
108 | * new serio device that supports the Touchwin protocol and registers it as | ||
109 | * an input device. | ||
110 | */ | ||
111 | |||
112 | static int tw_connect(struct serio *serio, struct serio_driver *drv) | ||
113 | { | ||
114 | struct tw *tw; | ||
115 | struct input_dev *input_dev; | ||
116 | int err; | ||
117 | |||
118 | tw = kzalloc(sizeof(struct tw), GFP_KERNEL); | ||
119 | input_dev = input_allocate_device(); | ||
120 | if (!tw || !input_dev) { | ||
121 | err = -ENOMEM; | ||
122 | goto fail1; | ||
123 | } | ||
124 | |||
125 | tw->serio = serio; | ||
126 | tw->dev = input_dev; | ||
127 | snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys); | ||
128 | |||
129 | input_dev->private = tw; | ||
130 | input_dev->name = "Touchwindow Serial TouchScreen"; | ||
131 | input_dev->phys = tw->phys; | ||
132 | input_dev->id.bustype = BUS_RS232; | ||
133 | input_dev->id.vendor = SERIO_TOUCHWIN; | ||
134 | input_dev->id.product = 0; | ||
135 | input_dev->id.version = 0x0100; | ||
136 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
137 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
138 | input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0); | ||
139 | input_set_abs_params(tw->dev, ABS_Y, TW_MIN_YC, TW_MAX_YC, 0, 0); | ||
140 | |||
141 | serio_set_drvdata(serio, tw); | ||
142 | |||
143 | err = serio_open(serio, drv); | ||
144 | if (err) | ||
145 | goto fail2; | ||
146 | |||
147 | err = input_register_device(tw->dev); | ||
148 | if (err) | ||
149 | goto fail3; | ||
150 | |||
151 | return 0; | ||
152 | |||
153 | fail3: serio_close(serio); | ||
154 | fail2: serio_set_drvdata(serio, NULL); | ||
155 | fail1: input_free_device(input_dev); | ||
156 | kfree(tw); | ||
157 | return err; | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * The serio driver structure. | ||
162 | */ | ||
163 | |||
164 | static struct serio_device_id tw_serio_ids[] = { | ||
165 | { | ||
166 | .type = SERIO_RS232, | ||
167 | .proto = SERIO_TOUCHWIN, | ||
168 | .id = SERIO_ANY, | ||
169 | .extra = SERIO_ANY, | ||
170 | }, | ||
171 | { 0 } | ||
172 | }; | ||
173 | |||
174 | MODULE_DEVICE_TABLE(serio, tw_serio_ids); | ||
175 | |||
176 | static struct serio_driver tw_drv = { | ||
177 | .driver = { | ||
178 | .name = "touchwin", | ||
179 | }, | ||
180 | .description = DRIVER_DESC, | ||
181 | .id_table = tw_serio_ids, | ||
182 | .interrupt = tw_interrupt, | ||
183 | .connect = tw_connect, | ||
184 | .disconnect = tw_disconnect, | ||
185 | }; | ||
186 | |||
187 | /* | ||
188 | * The functions for inserting/removing us as a module. | ||
189 | */ | ||
190 | |||
191 | static int __init tw_init(void) | ||
192 | { | ||
193 | serio_register_driver(&tw_drv); | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static void __exit tw_exit(void) | ||
198 | { | ||
199 | serio_unregister_driver(&tw_drv); | ||
200 | } | ||
201 | |||
202 | module_init(tw_init); | ||
203 | module_exit(tw_exit); | ||
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c index 00e3929c6288..a730c461227f 100644 --- a/drivers/input/tsdev.c +++ b/drivers/input/tsdev.c | |||
@@ -135,8 +135,6 @@ struct tsdev_list { | |||
135 | #define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration) | 135 | #define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration) |
136 | #define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration) | 136 | #define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration) |
137 | 137 | ||
138 | static struct input_handler tsdev_handler; | ||
139 | |||
140 | static struct tsdev *tsdev_table[TSDEV_MINORS/2]; | 138 | static struct tsdev *tsdev_table[TSDEV_MINORS/2]; |
141 | 139 | ||
142 | static int tsdev_fasync(int fd, struct file *file, int on) | 140 | static int tsdev_fasync(int fd, struct file *file, int on) |
@@ -263,7 +261,7 @@ static int tsdev_ioctl(struct inode *inode, struct file *file, | |||
263 | return retval; | 261 | return retval; |
264 | } | 262 | } |
265 | 263 | ||
266 | static struct file_operations tsdev_fops = { | 264 | static const struct file_operations tsdev_fops = { |
267 | .owner = THIS_MODULE, | 265 | .owner = THIS_MODULE, |
268 | .open = tsdev_open, | 266 | .open = tsdev_open, |
269 | .release = tsdev_release, | 267 | .release = tsdev_release, |
@@ -370,7 +368,7 @@ static void tsdev_event(struct input_handle *handle, unsigned int type, | |||
370 | 368 | ||
371 | static struct input_handle *tsdev_connect(struct input_handler *handler, | 369 | static struct input_handle *tsdev_connect(struct input_handler *handler, |
372 | struct input_dev *dev, | 370 | struct input_dev *dev, |
373 | struct input_device_id *id) | 371 | const struct input_device_id *id) |
374 | { | 372 | { |
375 | struct tsdev *tsdev; | 373 | struct tsdev *tsdev; |
376 | struct class_device *cdev; | 374 | struct class_device *cdev; |
@@ -443,7 +441,7 @@ static void tsdev_disconnect(struct input_handle *handle) | |||
443 | tsdev_free(tsdev); | 441 | tsdev_free(tsdev); |
444 | } | 442 | } |
445 | 443 | ||
446 | static struct input_device_id tsdev_ids[] = { | 444 | static const struct input_device_id tsdev_ids[] = { |
447 | { | 445 | { |
448 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, | 446 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, |
449 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, | 447 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, |
@@ -481,9 +479,7 @@ static struct input_handler tsdev_handler = { | |||
481 | 479 | ||
482 | static int __init tsdev_init(void) | 480 | static int __init tsdev_init(void) |
483 | { | 481 | { |
484 | input_register_handler(&tsdev_handler); | 482 | return input_register_handler(&tsdev_handler); |
485 | printk(KERN_INFO "ts: Compaq touchscreen protocol output\n"); | ||
486 | return 0; | ||
487 | } | 483 | } |
488 | 484 | ||
489 | static void __exit tsdev_exit(void) | 485 | static void __exit tsdev_exit(void) |
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index a102a58fe361..21cd22640080 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
@@ -60,16 +60,17 @@ config HID_FF | |||
60 | If unsure, say N. | 60 | If unsure, say N. |
61 | 61 | ||
62 | config HID_PID | 62 | config HID_PID |
63 | bool "PID Devices (Microsoft Sidewinder Force Feedback 2)" | 63 | bool "PID device support" |
64 | depends on HID_FF | 64 | depends on HID_FF |
65 | help | 65 | help |
66 | Say Y here if you have a PID-compliant joystick and wish to enable force | 66 | Say Y here if you have a PID-compliant device and wish to enable force |
67 | feedback for it. The Microsoft Sidewinder Force Feedback 2 is one such | 67 | feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such |
68 | device. | 68 | devices. |
69 | 69 | ||
70 | config LOGITECH_FF | 70 | config LOGITECH_FF |
71 | bool "Logitech WingMan *3D support" | 71 | bool "Logitech WingMan *3D support" |
72 | depends on HID_FF | 72 | depends on HID_FF |
73 | select INPUT_FF_MEMLESS if USB_HID | ||
73 | help | 74 | help |
74 | Say Y here if you have one of these devices: | 75 | Say Y here if you have one of these devices: |
75 | - Logitech WingMan Cordless RumblePad | 76 | - Logitech WingMan Cordless RumblePad |
@@ -81,12 +82,21 @@ config LOGITECH_FF | |||
81 | config THRUSTMASTER_FF | 82 | config THRUSTMASTER_FF |
82 | bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" | 83 | bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" |
83 | depends on HID_FF && EXPERIMENTAL | 84 | depends on HID_FF && EXPERIMENTAL |
85 | select INPUT_FF_MEMLESS if USB_HID | ||
84 | help | 86 | help |
85 | Say Y here if you have a THRUSTMASTER FireStore Dual Power 2, | 87 | Say Y here if you have a THRUSTMASTER FireStore Dual Power 2, |
86 | and want to enable force feedback support for it. | 88 | and want to enable force feedback support for it. |
87 | Note: if you say N here, this device will still be supported, but without | 89 | Note: if you say N here, this device will still be supported, but without |
88 | force feedback. | 90 | force feedback. |
89 | 91 | ||
92 | config ZEROPLUS_FF | ||
93 | bool "Zeroplus based game controller support" | ||
94 | depends on HID_FF | ||
95 | select INPUT_FF_MEMLESS if USB_HID | ||
96 | help | ||
97 | Say Y here if you have a Zeroplus based game controller and want to | ||
98 | enable force feedback for it. | ||
99 | |||
90 | config USB_HIDDEV | 100 | config USB_HIDDEV |
91 | bool "/dev/hiddev raw HID device support" | 101 | bool "/dev/hiddev raw HID device support" |
92 | depends on USB_HID | 102 | depends on USB_HID |
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 48551be324ac..295f459d1079 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile | |||
@@ -15,7 +15,7 @@ ifeq ($(CONFIG_USB_HIDINPUT),y) | |||
15 | usbhid-objs += hid-input.o | 15 | usbhid-objs += hid-input.o |
16 | endif | 16 | endif |
17 | ifeq ($(CONFIG_HID_PID),y) | 17 | ifeq ($(CONFIG_HID_PID),y) |
18 | usbhid-objs += pid.o | 18 | usbhid-objs += hid-pidff.o |
19 | endif | 19 | endif |
20 | ifeq ($(CONFIG_LOGITECH_FF),y) | 20 | ifeq ($(CONFIG_LOGITECH_FF),y) |
21 | usbhid-objs += hid-lgff.o | 21 | usbhid-objs += hid-lgff.o |
@@ -23,6 +23,9 @@ endif | |||
23 | ifeq ($(CONFIG_THRUSTMASTER_FF),y) | 23 | ifeq ($(CONFIG_THRUSTMASTER_FF),y) |
24 | usbhid-objs += hid-tmff.o | 24 | usbhid-objs += hid-tmff.o |
25 | endif | 25 | endif |
26 | ifeq ($(CONFIG_ZEROPLUS_FF),y) | ||
27 | usbhid-objs += hid-zpff.o | ||
28 | endif | ||
26 | ifeq ($(CONFIG_HID_FF),y) | 29 | ifeq ($(CONFIG_HID_FF),y) |
27 | usbhid-objs += hid-ff.o | 30 | usbhid-objs += hid-ff.o |
28 | endif | 31 | endif |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 81b1ea01a172..e0fd11605b43 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -543,8 +543,6 @@ static void hid_free_device(struct hid_device *device) | |||
543 | { | 543 | { |
544 | unsigned i,j; | 544 | unsigned i,j; |
545 | 545 | ||
546 | hid_ff_exit(device); | ||
547 | |||
548 | for (i = 0; i < HID_REPORT_TYPES; i++) { | 546 | for (i = 0; i < HID_REPORT_TYPES; i++) { |
549 | struct hid_report_enum *report_enum = device->report_enum + i; | 547 | struct hid_report_enum *report_enum = device->report_enum + i; |
550 | 548 | ||
@@ -1109,7 +1107,7 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) | |||
1109 | /* | 1107 | /* |
1110 | * Find a report field with a specified HID usage. | 1108 | * Find a report field with a specified HID usage. |
1111 | */ | 1109 | */ |
1112 | 1110 | #if 0 | |
1113 | struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type) | 1111 | struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type) |
1114 | { | 1112 | { |
1115 | struct hid_report *report; | 1113 | struct hid_report *report; |
@@ -1121,6 +1119,7 @@ struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_u | |||
1121 | return report->field[i]; | 1119 | return report->field[i]; |
1122 | return NULL; | 1120 | return NULL; |
1123 | } | 1121 | } |
1122 | #endif /* 0 */ | ||
1124 | 1123 | ||
1125 | static int hid_submit_out(struct hid_device *hid) | 1124 | static int hid_submit_out(struct hid_device *hid) |
1126 | { | 1125 | { |
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c index d5c91ee67991..a8fc46c721c5 100644 --- a/drivers/usb/input/hid-ff.c +++ b/drivers/usb/input/hid-ff.c | |||
@@ -44,45 +44,38 @@ struct hid_ff_initializer { | |||
44 | int (*init)(struct hid_device*); | 44 | int (*init)(struct hid_device*); |
45 | }; | 45 | }; |
46 | 46 | ||
47 | /* | ||
48 | * We try pidff when no other driver is found because PID is the | ||
49 | * standards compliant way of implementing force feedback in HID. | ||
50 | * pidff_init() will quickly abort if the device doesn't appear to | ||
51 | * be a PID device | ||
52 | */ | ||
47 | static struct hid_ff_initializer inits[] = { | 53 | static struct hid_ff_initializer inits[] = { |
48 | #ifdef CONFIG_LOGITECH_FF | 54 | #ifdef CONFIG_LOGITECH_FF |
49 | {0x46d, 0xc211, hid_lgff_init}, // Logitech Cordless rumble pad | 55 | { 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */ |
50 | {0x46d, 0xc283, hid_lgff_init}, // Logitech Wingman Force 3d | 56 | { 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */ |
51 | {0x46d, 0xc295, hid_lgff_init}, // Logitech MOMO force wheel | 57 | { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */ |
52 | {0x46d, 0xc219, hid_lgff_init}, // Logitech Cordless rumble pad 2 | 58 | { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */ |
53 | #endif | ||
54 | #ifdef CONFIG_HID_PID | ||
55 | {0x45e, 0x001b, hid_pid_init}, | ||
56 | #endif | 59 | #endif |
57 | #ifdef CONFIG_THRUSTMASTER_FF | 60 | #ifdef CONFIG_THRUSTMASTER_FF |
58 | {0x44f, 0xb304, hid_tmff_init}, | 61 | { 0x44f, 0xb304, hid_tmff_init }, |
59 | #endif | 62 | #endif |
60 | {0, 0, NULL} /* Terminating entry */ | 63 | #ifdef CONFIG_ZEROPLUS_FF |
64 | { 0xc12, 0x0005, hid_zpff_init }, | ||
65 | { 0xc12, 0x0030, hid_zpff_init }, | ||
66 | #endif | ||
67 | { 0, 0, hid_pidff_init} /* Matches anything */ | ||
61 | }; | 68 | }; |
62 | 69 | ||
63 | static struct hid_ff_initializer *hid_get_ff_init(__u16 idVendor, | ||
64 | __u16 idProduct) | ||
65 | { | ||
66 | struct hid_ff_initializer *init; | ||
67 | for (init = inits; | ||
68 | init->idVendor | ||
69 | && !(init->idVendor == idVendor | ||
70 | && init->idProduct == idProduct); | ||
71 | init++); | ||
72 | |||
73 | return init->idVendor? init : NULL; | ||
74 | } | ||
75 | |||
76 | int hid_ff_init(struct hid_device* hid) | 70 | int hid_ff_init(struct hid_device* hid) |
77 | { | 71 | { |
78 | struct hid_ff_initializer *init; | 72 | struct hid_ff_initializer *init; |
73 | int vendor = le16_to_cpu(hid->dev->descriptor.idVendor); | ||
74 | int product = le16_to_cpu(hid->dev->descriptor.idProduct); | ||
79 | 75 | ||
80 | init = hid_get_ff_init(le16_to_cpu(hid->dev->descriptor.idVendor), | 76 | for (init = inits; init->idVendor; init++) |
81 | le16_to_cpu(hid->dev->descriptor.idProduct)); | 77 | if (init->idVendor == vendor && init->idProduct == product) |
78 | break; | ||
82 | 79 | ||
83 | if (!init) { | ||
84 | dbg("hid_ff_init could not find initializer"); | ||
85 | return -ENOSYS; | ||
86 | } | ||
87 | return init->init(hid); | 80 | return init->init(hid); |
88 | } | 81 | } |
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 7208839f2dbf..4c62afbeb430 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c | |||
@@ -65,11 +65,9 @@ static const struct { | |||
65 | #define map_rel(c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0) | 65 | #define map_rel(c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0) |
66 | #define map_key(c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0) | 66 | #define map_key(c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0) |
67 | #define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) | 67 | #define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) |
68 | #define map_ff(c) do { usage->code = c; usage->type = EV_FF; bit = input->ffbit; max = FF_MAX; } while (0) | ||
69 | 68 | ||
70 | #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) | 69 | #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) |
71 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) | 70 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) |
72 | #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) | ||
73 | 71 | ||
74 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | 72 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK |
75 | 73 | ||
@@ -525,23 +523,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
525 | 523 | ||
526 | case HID_UP_PID: | 524 | case HID_UP_PID: |
527 | 525 | ||
528 | set_bit(EV_FF, input->evbit); | ||
529 | switch(usage->hid & HID_USAGE) { | 526 | switch(usage->hid & HID_USAGE) { |
530 | case 0x26: map_ff_effect(FF_CONSTANT); goto ignore; | ||
531 | case 0x27: map_ff_effect(FF_RAMP); goto ignore; | ||
532 | case 0x28: map_ff_effect(FF_CUSTOM); goto ignore; | ||
533 | case 0x30: map_ff_effect(FF_SQUARE); map_ff_effect(FF_PERIODIC); goto ignore; | ||
534 | case 0x31: map_ff_effect(FF_SINE); map_ff_effect(FF_PERIODIC); goto ignore; | ||
535 | case 0x32: map_ff_effect(FF_TRIANGLE); map_ff_effect(FF_PERIODIC); goto ignore; | ||
536 | case 0x33: map_ff_effect(FF_SAW_UP); map_ff_effect(FF_PERIODIC); goto ignore; | ||
537 | case 0x34: map_ff_effect(FF_SAW_DOWN); map_ff_effect(FF_PERIODIC); goto ignore; | ||
538 | case 0x40: map_ff_effect(FF_SPRING); goto ignore; | ||
539 | case 0x41: map_ff_effect(FF_DAMPER); goto ignore; | ||
540 | case 0x42: map_ff_effect(FF_INERTIA); goto ignore; | ||
541 | case 0x43: map_ff_effect(FF_FRICTION); goto ignore; | ||
542 | case 0x7e: map_ff(FF_GAIN); break; | ||
543 | case 0x83: input->ff_effects_max = field->value[0]; goto ignore; | ||
544 | case 0x98: map_ff(FF_AUTOCENTER); break; | ||
545 | case 0xa4: map_key_clear(BTN_DEAD); break; | 527 | case 0xa4: map_key_clear(BTN_DEAD); break; |
546 | default: goto ignore; | 528 | default: goto ignore; |
547 | } | 529 | } |
@@ -698,8 +680,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
698 | } | 680 | } |
699 | 681 | ||
700 | if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */ | 682 | if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */ |
701 | input->ff_effects_max = value; | 683 | dbg("Maximum Effects - %d",value); |
702 | dbg("Maximum Effects - %d",input->ff_effects_max); | ||
703 | return; | 684 | return; |
704 | } | 685 | } |
705 | 686 | ||
@@ -748,7 +729,7 @@ static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsign | |||
748 | int offset; | 729 | int offset; |
749 | 730 | ||
750 | if (type == EV_FF) | 731 | if (type == EV_FF) |
751 | return hid_ff_event(hid, dev, type, code, value); | 732 | return input_ff_event(dev, type, code, value); |
752 | 733 | ||
753 | if (type != EV_LED) | 734 | if (type != EV_LED) |
754 | return -1; | 735 | return -1; |
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c index f07d44357ff1..93da222b6da8 100644 --- a/drivers/usb/input/hid-lgff.c +++ b/drivers/usb/input/hid-lgff.c | |||
@@ -1,12 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * $$ | ||
3 | * | ||
4 | * Force feedback support for hid-compliant for some of the devices from | 2 | * Force feedback support for hid-compliant for some of the devices from |
5 | * Logitech, namely: | 3 | * Logitech, namely: |
6 | * - WingMan Cordless RumblePad | 4 | * - WingMan Cordless RumblePad |
7 | * - WingMan Force 3D | 5 | * - WingMan Force 3D |
8 | * | 6 | * |
9 | * Copyright (c) 2002-2004 Johann Deneux | 7 | * Copyright (c) 2002-2004 Johann Deneux |
8 | * Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
10 | */ | 9 | */ |
11 | 10 | ||
12 | /* | 11 | /* |
@@ -29,495 +28,117 @@ | |||
29 | */ | 28 | */ |
30 | 29 | ||
31 | #include <linux/input.h> | 30 | #include <linux/input.h> |
32 | #include <linux/sched.h> | ||
33 | |||
34 | //#define DEBUG | ||
35 | #include <linux/usb.h> | 31 | #include <linux/usb.h> |
36 | |||
37 | #include <linux/circ_buf.h> | ||
38 | |||
39 | #include "hid.h" | 32 | #include "hid.h" |
40 | #include "fixp-arith.h" | ||
41 | |||
42 | |||
43 | /* Periodicity of the update */ | ||
44 | #define PERIOD (HZ/10) | ||
45 | |||
46 | #define RUN_AT(t) (jiffies + (t)) | ||
47 | |||
48 | /* Effect status */ | ||
49 | #define EFFECT_STARTED 0 /* Effect is going to play after some time | ||
50 | (ff_replay.delay) */ | ||
51 | #define EFFECT_PLAYING 1 /* Effect is being played */ | ||
52 | #define EFFECT_USED 2 | ||
53 | |||
54 | // For lgff_device::flags | ||
55 | #define DEVICE_CLOSING 0 /* The driver is being unitialised */ | ||
56 | |||
57 | /* Check that the current process can access an effect */ | ||
58 | #define CHECK_OWNERSHIP(effect) (current->pid == 0 \ | ||
59 | || effect.owner == current->pid) | ||
60 | |||
61 | #define LGFF_CHECK_OWNERSHIP(i, l) \ | ||
62 | (i>=0 && i<LGFF_EFFECTS \ | ||
63 | && test_bit(EFFECT_USED, l->effects[i].flags) \ | ||
64 | && CHECK_OWNERSHIP(l->effects[i])) | ||
65 | |||
66 | #define LGFF_EFFECTS 8 | ||
67 | 33 | ||
68 | struct device_type { | 34 | struct device_type { |
69 | u16 idVendor; | 35 | u16 idVendor; |
70 | u16 idProduct; | 36 | u16 idProduct; |
71 | signed short *ff; | 37 | const signed short *ff; |
72 | }; | ||
73 | |||
74 | struct lgff_effect { | ||
75 | pid_t owner; | ||
76 | |||
77 | struct ff_effect effect; | ||
78 | |||
79 | unsigned long flags[1]; | ||
80 | unsigned int count; /* Number of times left to play */ | ||
81 | unsigned long started_at; /* When the effect started to play */ | ||
82 | }; | ||
83 | |||
84 | struct lgff_device { | ||
85 | struct hid_device* hid; | ||
86 | |||
87 | struct hid_report* constant; | ||
88 | struct hid_report* rumble; | ||
89 | struct hid_report* condition; | ||
90 | |||
91 | struct lgff_effect effects[LGFF_EFFECTS]; | ||
92 | spinlock_t lock; /* device-level lock. Having locks on | ||
93 | a per-effect basis could be nice, but | ||
94 | isn't really necessary */ | ||
95 | |||
96 | unsigned long flags[1]; /* Contains various information about the | ||
97 | state of the driver for this device */ | ||
98 | |||
99 | struct timer_list timer; | ||
100 | }; | 38 | }; |
101 | 39 | ||
102 | /* Callbacks */ | 40 | static const signed short ff_rumble[] = { |
103 | static void hid_lgff_exit(struct hid_device* hid); | ||
104 | static int hid_lgff_event(struct hid_device *hid, struct input_dev *input, | ||
105 | unsigned int type, unsigned int code, int value); | ||
106 | static int hid_lgff_flush(struct input_dev *input, struct file *file); | ||
107 | static int hid_lgff_upload_effect(struct input_dev *input, | ||
108 | struct ff_effect *effect); | ||
109 | static int hid_lgff_erase(struct input_dev *input, int id); | ||
110 | |||
111 | /* Local functions */ | ||
112 | static void hid_lgff_input_init(struct hid_device* hid); | ||
113 | static void hid_lgff_timer(unsigned long timer_data); | ||
114 | static struct hid_report* hid_lgff_duplicate_report(struct hid_report*); | ||
115 | static void hid_lgff_delete_report(struct hid_report*); | ||
116 | |||
117 | static signed short ff_rumble[] = { | ||
118 | FF_RUMBLE, | 41 | FF_RUMBLE, |
119 | -1 | 42 | -1 |
120 | }; | 43 | }; |
121 | 44 | ||
122 | static signed short ff_joystick[] = { | 45 | static const signed short ff_joystick[] = { |
123 | FF_CONSTANT, | 46 | FF_CONSTANT, |
124 | -1 | 47 | -1 |
125 | }; | 48 | }; |
126 | 49 | ||
127 | static struct device_type devices[] = { | 50 | static const struct device_type devices[] = { |
128 | {0x046d, 0xc211, ff_rumble}, | 51 | { 0x046d, 0xc211, ff_rumble }, |
129 | {0x046d, 0xc219, ff_rumble}, | 52 | { 0x046d, 0xc219, ff_rumble }, |
130 | {0x046d, 0xc283, ff_joystick}, | 53 | { 0x046d, 0xc283, ff_joystick }, |
131 | {0x0000, 0x0000, ff_joystick} | 54 | { 0x0000, 0x0000, ff_joystick } |
132 | }; | 55 | }; |
133 | 56 | ||
57 | static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect) | ||
58 | { | ||
59 | struct hid_device *hid = dev->private; | ||
60 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
61 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
62 | int x, y; | ||
63 | unsigned int left, right; | ||
64 | |||
65 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | ||
66 | |||
67 | switch (effect->type) { | ||
68 | case FF_CONSTANT: | ||
69 | x = effect->u.ramp.start_level + 0x7f; /* 0x7f is center */ | ||
70 | y = effect->u.ramp.end_level + 0x7f; | ||
71 | CLAMP(x); | ||
72 | CLAMP(y); | ||
73 | report->field[0]->value[0] = 0x51; | ||
74 | report->field[0]->value[1] = 0x08; | ||
75 | report->field[0]->value[2] = x; | ||
76 | report->field[0]->value[3] = y; | ||
77 | dbg("(x, y)=(%04x, %04x)", x, y); | ||
78 | hid_submit_report(hid, report, USB_DIR_OUT); | ||
79 | break; | ||
80 | |||
81 | case FF_RUMBLE: | ||
82 | right = effect->u.rumble.strong_magnitude; | ||
83 | left = effect->u.rumble.weak_magnitude; | ||
84 | right = right * 0xff / 0xffff; | ||
85 | left = left * 0xff / 0xffff; | ||
86 | CLAMP(left); | ||
87 | CLAMP(right); | ||
88 | report->field[0]->value[0] = 0x42; | ||
89 | report->field[0]->value[1] = 0x00; | ||
90 | report->field[0]->value[2] = left; | ||
91 | report->field[0]->value[3] = right; | ||
92 | dbg("(left, right)=(%04x, %04x)", left, right); | ||
93 | hid_submit_report(hid, report, USB_DIR_OUT); | ||
94 | break; | ||
95 | } | ||
96 | return 0; | ||
97 | } | ||
98 | |||
134 | int hid_lgff_init(struct hid_device* hid) | 99 | int hid_lgff_init(struct hid_device* hid) |
135 | { | 100 | { |
136 | struct lgff_device *private; | 101 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); |
137 | struct hid_report* report; | 102 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; |
138 | struct hid_field* field; | 103 | struct input_dev *dev = hidinput->input; |
104 | struct hid_report *report; | ||
105 | struct hid_field *field; | ||
106 | int error; | ||
107 | int i, j; | ||
139 | 108 | ||
140 | /* Find the report to use */ | 109 | /* Find the report to use */ |
141 | if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { | 110 | if (list_empty(report_list)) { |
142 | err("No output report found"); | 111 | err("No output report found"); |
143 | return -1; | 112 | return -1; |
144 | } | 113 | } |
114 | |||
145 | /* Check that the report looks ok */ | 115 | /* Check that the report looks ok */ |
146 | report = (struct hid_report*)hid->report_enum[HID_OUTPUT_REPORT].report_list.next; | 116 | report = list_entry(report_list->next, struct hid_report, list); |
147 | if (!report) { | 117 | if (!report) { |
148 | err("NULL output report"); | 118 | err("NULL output report"); |
149 | return -1; | 119 | return -1; |
150 | } | 120 | } |
121 | |||
151 | field = report->field[0]; | 122 | field = report->field[0]; |
152 | if (!field) { | 123 | if (!field) { |
153 | err("NULL field"); | 124 | err("NULL field"); |
154 | return -1; | 125 | return -1; |
155 | } | 126 | } |
156 | 127 | ||
157 | private = kzalloc(sizeof(struct lgff_device), GFP_KERNEL); | 128 | for (i = 0; i < ARRAY_SIZE(devices); i++) { |
158 | if (!private) | 129 | if (dev->id.vendor == devices[i].idVendor && |
159 | return -1; | 130 | dev->id.product == devices[i].idProduct) { |
160 | hid->ff_private = private; | 131 | for (j = 0; devices[i].ff[j] >= 0; j++) |
161 | 132 | set_bit(devices[i].ff[j], dev->ffbit); | |
162 | /* Input init */ | 133 | break; |
163 | hid_lgff_input_init(hid); | ||
164 | |||
165 | |||
166 | private->constant = hid_lgff_duplicate_report(report); | ||
167 | if (!private->constant) { | ||
168 | kfree(private); | ||
169 | return -1; | ||
170 | } | ||
171 | private->constant->field[0]->value[0] = 0x51; | ||
172 | private->constant->field[0]->value[1] = 0x08; | ||
173 | private->constant->field[0]->value[2] = 0x7f; | ||
174 | private->constant->field[0]->value[3] = 0x7f; | ||
175 | |||
176 | private->rumble = hid_lgff_duplicate_report(report); | ||
177 | if (!private->rumble) { | ||
178 | hid_lgff_delete_report(private->constant); | ||
179 | kfree(private); | ||
180 | return -1; | ||
181 | } | ||
182 | private->rumble->field[0]->value[0] = 0x42; | ||
183 | |||
184 | |||
185 | private->condition = hid_lgff_duplicate_report(report); | ||
186 | if (!private->condition) { | ||
187 | hid_lgff_delete_report(private->rumble); | ||
188 | hid_lgff_delete_report(private->constant); | ||
189 | kfree(private); | ||
190 | return -1; | ||
191 | } | ||
192 | |||
193 | private->hid = hid; | ||
194 | |||
195 | spin_lock_init(&private->lock); | ||
196 | init_timer(&private->timer); | ||
197 | private->timer.data = (unsigned long)private; | ||
198 | private->timer.function = hid_lgff_timer; | ||
199 | |||
200 | /* Event and exit callbacks */ | ||
201 | hid->ff_exit = hid_lgff_exit; | ||
202 | hid->ff_event = hid_lgff_event; | ||
203 | |||
204 | /* Start the update task */ | ||
205 | private->timer.expires = RUN_AT(PERIOD); | ||
206 | add_timer(&private->timer); /*TODO: only run the timer when at least | ||
207 | one effect is playing */ | ||
208 | |||
209 | printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report) | ||
215 | { | ||
216 | struct hid_report* ret; | ||
217 | |||
218 | ret = kmalloc(sizeof(struct lgff_device), GFP_KERNEL); | ||
219 | if (!ret) | ||
220 | return NULL; | ||
221 | *ret = *report; | ||
222 | |||
223 | ret->field[0] = kmalloc(sizeof(struct hid_field), GFP_KERNEL); | ||
224 | if (!ret->field[0]) { | ||
225 | kfree(ret); | ||
226 | return NULL; | ||
227 | } | ||
228 | *ret->field[0] = *report->field[0]; | ||
229 | |||
230 | ret->field[0]->value = kzalloc(sizeof(s32[8]), GFP_KERNEL); | ||
231 | if (!ret->field[0]->value) { | ||
232 | kfree(ret->field[0]); | ||
233 | kfree(ret); | ||
234 | return NULL; | ||
235 | } | ||
236 | |||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | static void hid_lgff_delete_report(struct hid_report* report) | ||
241 | { | ||
242 | if (report) { | ||
243 | kfree(report->field[0]->value); | ||
244 | kfree(report->field[0]); | ||
245 | kfree(report); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | static void hid_lgff_input_init(struct hid_device* hid) | ||
250 | { | ||
251 | struct device_type* dev = devices; | ||
252 | signed short* ff; | ||
253 | u16 idVendor = le16_to_cpu(hid->dev->descriptor.idVendor); | ||
254 | u16 idProduct = le16_to_cpu(hid->dev->descriptor.idProduct); | ||
255 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
256 | struct input_dev *input_dev = hidinput->input; | ||
257 | |||
258 | while (dev->idVendor && (idVendor != dev->idVendor || idProduct != dev->idProduct)) | ||
259 | dev++; | ||
260 | |||
261 | for (ff = dev->ff; *ff >= 0; ff++) | ||
262 | set_bit(*ff, input_dev->ffbit); | ||
263 | |||
264 | input_dev->upload_effect = hid_lgff_upload_effect; | ||
265 | input_dev->flush = hid_lgff_flush; | ||
266 | |||
267 | set_bit(EV_FF, input_dev->evbit); | ||
268 | input_dev->ff_effects_max = LGFF_EFFECTS; | ||
269 | } | ||
270 | |||
271 | static void hid_lgff_exit(struct hid_device* hid) | ||
272 | { | ||
273 | struct lgff_device *lgff = hid->ff_private; | ||
274 | |||
275 | set_bit(DEVICE_CLOSING, lgff->flags); | ||
276 | del_timer_sync(&lgff->timer); | ||
277 | |||
278 | hid_lgff_delete_report(lgff->condition); | ||
279 | hid_lgff_delete_report(lgff->rumble); | ||
280 | hid_lgff_delete_report(lgff->constant); | ||
281 | |||
282 | kfree(lgff); | ||
283 | } | ||
284 | |||
285 | static int hid_lgff_event(struct hid_device *hid, struct input_dev* input, | ||
286 | unsigned int type, unsigned int code, int value) | ||
287 | { | ||
288 | struct lgff_device *lgff = hid->ff_private; | ||
289 | struct lgff_effect *effect = lgff->effects + code; | ||
290 | unsigned long flags; | ||
291 | |||
292 | if (type != EV_FF) return -EINVAL; | ||
293 | if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; | ||
294 | if (value < 0) return -EINVAL; | ||
295 | |||
296 | spin_lock_irqsave(&lgff->lock, flags); | ||
297 | |||
298 | if (value > 0) { | ||
299 | if (test_bit(EFFECT_STARTED, effect->flags)) { | ||
300 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
301 | return -EBUSY; | ||
302 | } | ||
303 | if (test_bit(EFFECT_PLAYING, effect->flags)) { | ||
304 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
305 | return -EBUSY; | ||
306 | } | ||
307 | |||
308 | effect->count = value; | ||
309 | |||
310 | if (effect->effect.replay.delay) { | ||
311 | set_bit(EFFECT_STARTED, effect->flags); | ||
312 | } else { | ||
313 | set_bit(EFFECT_PLAYING, effect->flags); | ||
314 | } | ||
315 | effect->started_at = jiffies; | ||
316 | } | ||
317 | else { /* value == 0 */ | ||
318 | clear_bit(EFFECT_STARTED, effect->flags); | ||
319 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
320 | } | ||
321 | |||
322 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
323 | |||
324 | return 0; | ||
325 | |||
326 | } | ||
327 | |||
328 | /* Erase all effects this process owns */ | ||
329 | static int hid_lgff_flush(struct input_dev *dev, struct file *file) | ||
330 | { | ||
331 | struct hid_device *hid = dev->private; | ||
332 | struct lgff_device *lgff = hid->ff_private; | ||
333 | int i; | ||
334 | |||
335 | for (i=0; i<dev->ff_effects_max; ++i) { | ||
336 | |||
337 | /*NOTE: no need to lock here. The only times EFFECT_USED is | ||
338 | modified is when effects are uploaded or when an effect is | ||
339 | erased. But a process cannot close its dev/input/eventX fd | ||
340 | and perform ioctls on the same fd all at the same time */ | ||
341 | if ( current->pid == lgff->effects[i].owner | ||
342 | && test_bit(EFFECT_USED, lgff->effects[i].flags)) { | ||
343 | |||
344 | if (hid_lgff_erase(dev, i)) | ||
345 | warn("erase effect %d failed", i); | ||
346 | } | ||
347 | |||
348 | } | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static int hid_lgff_erase(struct input_dev *dev, int id) | ||
354 | { | ||
355 | struct hid_device *hid = dev->private; | ||
356 | struct lgff_device *lgff = hid->ff_private; | ||
357 | unsigned long flags; | ||
358 | |||
359 | if (!LGFF_CHECK_OWNERSHIP(id, lgff)) return -EACCES; | ||
360 | |||
361 | spin_lock_irqsave(&lgff->lock, flags); | ||
362 | lgff->effects[id].flags[0] = 0; | ||
363 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static int hid_lgff_upload_effect(struct input_dev* input, | ||
369 | struct ff_effect* effect) | ||
370 | { | ||
371 | struct hid_device *hid = input->private; | ||
372 | struct lgff_device *lgff = hid->ff_private; | ||
373 | struct lgff_effect new; | ||
374 | int id; | ||
375 | unsigned long flags; | ||
376 | |||
377 | dbg("ioctl rumble"); | ||
378 | |||
379 | if (!test_bit(effect->type, input->ffbit)) return -EINVAL; | ||
380 | |||
381 | spin_lock_irqsave(&lgff->lock, flags); | ||
382 | |||
383 | if (effect->id == -1) { | ||
384 | int i; | ||
385 | |||
386 | for (i=0; i<LGFF_EFFECTS && test_bit(EFFECT_USED, lgff->effects[i].flags); ++i); | ||
387 | if (i >= LGFF_EFFECTS) { | ||
388 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
389 | return -ENOSPC; | ||
390 | } | 134 | } |
391 | |||
392 | effect->id = i; | ||
393 | lgff->effects[i].owner = current->pid; | ||
394 | lgff->effects[i].flags[0] = 0; | ||
395 | set_bit(EFFECT_USED, lgff->effects[i].flags); | ||
396 | } | 135 | } |
397 | else if (!LGFF_CHECK_OWNERSHIP(effect->id, lgff)) { | ||
398 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
399 | return -EACCES; | ||
400 | } | ||
401 | |||
402 | id = effect->id; | ||
403 | new = lgff->effects[id]; | ||
404 | |||
405 | new.effect = *effect; | ||
406 | |||
407 | if (test_bit(EFFECT_STARTED, lgff->effects[id].flags) | ||
408 | || test_bit(EFFECT_STARTED, lgff->effects[id].flags)) { | ||
409 | |||
410 | /* Changing replay parameters is not allowed (for the time | ||
411 | being) */ | ||
412 | if (new.effect.replay.delay != lgff->effects[id].effect.replay.delay | ||
413 | || new.effect.replay.length != lgff->effects[id].effect.replay.length) { | ||
414 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
415 | return -ENOSYS; | ||
416 | } | ||
417 | 136 | ||
418 | lgff->effects[id] = new; | 137 | error = input_ff_create_memless(dev, NULL, hid_lgff_play); |
138 | if (error) | ||
139 | return error; | ||
419 | 140 | ||
420 | } else { | 141 | printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); |
421 | lgff->effects[id] = new; | ||
422 | } | ||
423 | 142 | ||
424 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
425 | return 0; | 143 | return 0; |
426 | } | 144 | } |
427 | |||
428 | static void hid_lgff_timer(unsigned long timer_data) | ||
429 | { | ||
430 | struct lgff_device *lgff = (struct lgff_device*)timer_data; | ||
431 | struct hid_device *hid = lgff->hid; | ||
432 | unsigned long flags; | ||
433 | int x = 0x7f, y = 0x7f; // Coordinates of constant effects | ||
434 | unsigned int left = 0, right = 0; // Rumbling | ||
435 | int i; | ||
436 | |||
437 | spin_lock_irqsave(&lgff->lock, flags); | ||
438 | |||
439 | for (i=0; i<LGFF_EFFECTS; ++i) { | ||
440 | struct lgff_effect* effect = lgff->effects +i; | ||
441 | |||
442 | if (test_bit(EFFECT_PLAYING, effect->flags)) { | ||
443 | |||
444 | switch (effect->effect.type) { | ||
445 | case FF_CONSTANT: { | ||
446 | //TODO: handle envelopes | ||
447 | int degrees = effect->effect.direction * 360 >> 16; | ||
448 | x += fixp_mult(fixp_sin(degrees), | ||
449 | fixp_new16(effect->effect.u.constant.level)); | ||
450 | y += fixp_mult(-fixp_cos(degrees), | ||
451 | fixp_new16(effect->effect.u.constant.level)); | ||
452 | } break; | ||
453 | case FF_RUMBLE: | ||
454 | right += effect->effect.u.rumble.strong_magnitude; | ||
455 | left += effect->effect.u.rumble.weak_magnitude; | ||
456 | break; | ||
457 | }; | ||
458 | |||
459 | /* One run of the effect is finished playing */ | ||
460 | if (time_after(jiffies, | ||
461 | effect->started_at | ||
462 | + effect->effect.replay.delay*HZ/1000 | ||
463 | + effect->effect.replay.length*HZ/1000)) { | ||
464 | dbg("Finished playing once %d", i); | ||
465 | if (--effect->count <= 0) { | ||
466 | dbg("Stopped %d", i); | ||
467 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
468 | } | ||
469 | else { | ||
470 | dbg("Start again %d", i); | ||
471 | if (effect->effect.replay.length != 0) { | ||
472 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
473 | set_bit(EFFECT_STARTED, effect->flags); | ||
474 | } | ||
475 | effect->started_at = jiffies; | ||
476 | } | ||
477 | } | ||
478 | |||
479 | } else if (test_bit(EFFECT_STARTED, lgff->effects[i].flags)) { | ||
480 | /* Check if we should start playing the effect */ | ||
481 | if (time_after(jiffies, | ||
482 | lgff->effects[i].started_at | ||
483 | + lgff->effects[i].effect.replay.delay*HZ/1000)) { | ||
484 | dbg("Now playing %d", i); | ||
485 | clear_bit(EFFECT_STARTED, lgff->effects[i].flags); | ||
486 | set_bit(EFFECT_PLAYING, lgff->effects[i].flags); | ||
487 | } | ||
488 | } | ||
489 | } | ||
490 | |||
491 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | ||
492 | |||
493 | // Clamp values | ||
494 | CLAMP(x); | ||
495 | CLAMP(y); | ||
496 | CLAMP(left); | ||
497 | CLAMP(right); | ||
498 | |||
499 | #undef CLAMP | ||
500 | |||
501 | if (x != lgff->constant->field[0]->value[2] | ||
502 | || y != lgff->constant->field[0]->value[3]) { | ||
503 | lgff->constant->field[0]->value[2] = x; | ||
504 | lgff->constant->field[0]->value[3] = y; | ||
505 | dbg("(x,y)=(%04x, %04x)", x, y); | ||
506 | hid_submit_report(hid, lgff->constant, USB_DIR_OUT); | ||
507 | } | ||
508 | |||
509 | if (left != lgff->rumble->field[0]->value[2] | ||
510 | || right != lgff->rumble->field[0]->value[3]) { | ||
511 | lgff->rumble->field[0]->value[2] = left; | ||
512 | lgff->rumble->field[0]->value[3] = right; | ||
513 | dbg("(left,right)=(%04x, %04x)", left, right); | ||
514 | hid_submit_report(hid, lgff->rumble, USB_DIR_OUT); | ||
515 | } | ||
516 | |||
517 | if (!test_bit(DEVICE_CLOSING, lgff->flags)) { | ||
518 | lgff->timer.expires = RUN_AT(PERIOD); | ||
519 | add_timer(&lgff->timer); | ||
520 | } | ||
521 | |||
522 | spin_unlock_irqrestore(&lgff->lock, flags); | ||
523 | } | ||
diff --git a/drivers/usb/input/hid-pidff.c b/drivers/usb/input/hid-pidff.c new file mode 100644 index 000000000000..5420c13eb8eb --- /dev/null +++ b/drivers/usb/input/hid-pidff.c | |||
@@ -0,0 +1,1330 @@ | |||
1 | /* | ||
2 | * Force feedback driver for USB HID PID compliant devices | ||
3 | * | ||
4 | * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
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 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | /* #define DEBUG */ | ||
24 | |||
25 | #define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg) | ||
26 | |||
27 | #include <linux/sched.h> | ||
28 | #include <linux/input.h> | ||
29 | #include <linux/usb.h> | ||
30 | |||
31 | #include "hid.h" | ||
32 | |||
33 | #define PID_EFFECTS_MAX 64 | ||
34 | |||
35 | /* Report usage table used to put reports into an array */ | ||
36 | |||
37 | #define PID_SET_EFFECT 0 | ||
38 | #define PID_EFFECT_OPERATION 1 | ||
39 | #define PID_DEVICE_GAIN 2 | ||
40 | #define PID_POOL 3 | ||
41 | #define PID_BLOCK_LOAD 4 | ||
42 | #define PID_BLOCK_FREE 5 | ||
43 | #define PID_DEVICE_CONTROL 6 | ||
44 | #define PID_CREATE_NEW_EFFECT 7 | ||
45 | |||
46 | #define PID_REQUIRED_REPORTS 7 | ||
47 | |||
48 | #define PID_SET_ENVELOPE 8 | ||
49 | #define PID_SET_CONDITION 9 | ||
50 | #define PID_SET_PERIODIC 10 | ||
51 | #define PID_SET_CONSTANT 11 | ||
52 | #define PID_SET_RAMP 12 | ||
53 | static const u8 pidff_reports[] = { | ||
54 | 0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab, | ||
55 | 0x5a, 0x5f, 0x6e, 0x73, 0x74 | ||
56 | }; | ||
57 | |||
58 | /* device_control is really 0x95, but 0x96 specified as it is the usage of | ||
59 | the only field in that report */ | ||
60 | |||
61 | /* Value usage tables used to put fields and values into arrays */ | ||
62 | |||
63 | #define PID_EFFECT_BLOCK_INDEX 0 | ||
64 | |||
65 | #define PID_DURATION 1 | ||
66 | #define PID_GAIN 2 | ||
67 | #define PID_TRIGGER_BUTTON 3 | ||
68 | #define PID_TRIGGER_REPEAT_INT 4 | ||
69 | #define PID_DIRECTION_ENABLE 5 | ||
70 | #define PID_START_DELAY 6 | ||
71 | static const u8 pidff_set_effect[] = { | ||
72 | 0x22, 0x50, 0x52, 0x53, 0x54, 0x56, 0xa7 | ||
73 | }; | ||
74 | |||
75 | #define PID_ATTACK_LEVEL 1 | ||
76 | #define PID_ATTACK_TIME 2 | ||
77 | #define PID_FADE_LEVEL 3 | ||
78 | #define PID_FADE_TIME 4 | ||
79 | static const u8 pidff_set_envelope[] = { 0x22, 0x5b, 0x5c, 0x5d, 0x5e }; | ||
80 | |||
81 | #define PID_PARAM_BLOCK_OFFSET 1 | ||
82 | #define PID_CP_OFFSET 2 | ||
83 | #define PID_POS_COEFFICIENT 3 | ||
84 | #define PID_NEG_COEFFICIENT 4 | ||
85 | #define PID_POS_SATURATION 5 | ||
86 | #define PID_NEG_SATURATION 6 | ||
87 | #define PID_DEAD_BAND 7 | ||
88 | static const u8 pidff_set_condition[] = { | ||
89 | 0x22, 0x23, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65 | ||
90 | }; | ||
91 | |||
92 | #define PID_MAGNITUDE 1 | ||
93 | #define PID_OFFSET 2 | ||
94 | #define PID_PHASE 3 | ||
95 | #define PID_PERIOD 4 | ||
96 | static const u8 pidff_set_periodic[] = { 0x22, 0x70, 0x6f, 0x71, 0x72 }; | ||
97 | static const u8 pidff_set_constant[] = { 0x22, 0x70 }; | ||
98 | |||
99 | #define PID_RAMP_START 1 | ||
100 | #define PID_RAMP_END 2 | ||
101 | static const u8 pidff_set_ramp[] = { 0x22, 0x75, 0x76 }; | ||
102 | |||
103 | #define PID_RAM_POOL_AVAILABLE 1 | ||
104 | static const u8 pidff_block_load[] = { 0x22, 0xac }; | ||
105 | |||
106 | #define PID_LOOP_COUNT 1 | ||
107 | static const u8 pidff_effect_operation[] = { 0x22, 0x7c }; | ||
108 | |||
109 | static const u8 pidff_block_free[] = { 0x22 }; | ||
110 | |||
111 | #define PID_DEVICE_GAIN_FIELD 0 | ||
112 | static const u8 pidff_device_gain[] = { 0x7e }; | ||
113 | |||
114 | #define PID_RAM_POOL_SIZE 0 | ||
115 | #define PID_SIMULTANEOUS_MAX 1 | ||
116 | #define PID_DEVICE_MANAGED_POOL 2 | ||
117 | static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 }; | ||
118 | |||
119 | /* Special field key tables used to put special field keys into arrays */ | ||
120 | |||
121 | #define PID_ENABLE_ACTUATORS 0 | ||
122 | #define PID_RESET 1 | ||
123 | static const u8 pidff_device_control[] = { 0x97, 0x9a }; | ||
124 | |||
125 | #define PID_CONSTANT 0 | ||
126 | #define PID_RAMP 1 | ||
127 | #define PID_SQUARE 2 | ||
128 | #define PID_SINE 3 | ||
129 | #define PID_TRIANGLE 4 | ||
130 | #define PID_SAW_UP 5 | ||
131 | #define PID_SAW_DOWN 6 | ||
132 | #define PID_SPRING 7 | ||
133 | #define PID_DAMPER 8 | ||
134 | #define PID_INERTIA 9 | ||
135 | #define PID_FRICTION 10 | ||
136 | static const u8 pidff_effect_types[] = { | ||
137 | 0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34, | ||
138 | 0x40, 0x41, 0x42, 0x43 | ||
139 | }; | ||
140 | |||
141 | #define PID_BLOCK_LOAD_SUCCESS 0 | ||
142 | #define PID_BLOCK_LOAD_FULL 1 | ||
143 | static const u8 pidff_block_load_status[] = { 0x8c, 0x8d }; | ||
144 | |||
145 | #define PID_EFFECT_START 0 | ||
146 | #define PID_EFFECT_STOP 1 | ||
147 | static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b }; | ||
148 | |||
149 | struct pidff_usage { | ||
150 | struct hid_field *field; | ||
151 | s32 *value; | ||
152 | }; | ||
153 | |||
154 | struct pidff_device { | ||
155 | struct hid_device *hid; | ||
156 | |||
157 | struct hid_report *reports[sizeof(pidff_reports)]; | ||
158 | |||
159 | struct pidff_usage set_effect[sizeof(pidff_set_effect)]; | ||
160 | struct pidff_usage set_envelope[sizeof(pidff_set_envelope)]; | ||
161 | struct pidff_usage set_condition[sizeof(pidff_set_condition)]; | ||
162 | struct pidff_usage set_periodic[sizeof(pidff_set_periodic)]; | ||
163 | struct pidff_usage set_constant[sizeof(pidff_set_constant)]; | ||
164 | struct pidff_usage set_ramp[sizeof(pidff_set_ramp)]; | ||
165 | |||
166 | struct pidff_usage device_gain[sizeof(pidff_device_gain)]; | ||
167 | struct pidff_usage block_load[sizeof(pidff_block_load)]; | ||
168 | struct pidff_usage pool[sizeof(pidff_pool)]; | ||
169 | struct pidff_usage effect_operation[sizeof(pidff_effect_operation)]; | ||
170 | struct pidff_usage block_free[sizeof(pidff_block_free)]; | ||
171 | |||
172 | /* Special field is a field that is not composed of | ||
173 | usage<->value pairs that pidff_usage values are */ | ||
174 | |||
175 | /* Special field in create_new_effect */ | ||
176 | struct hid_field *create_new_effect_type; | ||
177 | |||
178 | /* Special fields in set_effect */ | ||
179 | struct hid_field *set_effect_type; | ||
180 | struct hid_field *effect_direction; | ||
181 | |||
182 | /* Special field in device_control */ | ||
183 | struct hid_field *device_control; | ||
184 | |||
185 | /* Special field in block_load */ | ||
186 | struct hid_field *block_load_status; | ||
187 | |||
188 | /* Special field in effect_operation */ | ||
189 | struct hid_field *effect_operation_status; | ||
190 | |||
191 | int control_id[sizeof(pidff_device_control)]; | ||
192 | int type_id[sizeof(pidff_effect_types)]; | ||
193 | int status_id[sizeof(pidff_block_load_status)]; | ||
194 | int operation_id[sizeof(pidff_effect_operation_status)]; | ||
195 | |||
196 | int pid_id[PID_EFFECTS_MAX]; | ||
197 | }; | ||
198 | |||
199 | /* | ||
200 | * Scale an unsigned value with range 0..max for the given field | ||
201 | */ | ||
202 | static int pidff_rescale(int i, int max, struct hid_field *field) | ||
203 | { | ||
204 | return i * (field->logical_maximum - field->logical_minimum) / max + | ||
205 | field->logical_minimum; | ||
206 | } | ||
207 | |||
208 | /* | ||
209 | * Scale a signed value in range -0x8000..0x7fff for the given field | ||
210 | */ | ||
211 | static int pidff_rescale_signed(int i, struct hid_field *field) | ||
212 | { | ||
213 | return i == 0 ? 0 : i > | ||
214 | 0 ? i * field->logical_maximum / 0x7fff : i * | ||
215 | field->logical_minimum / -0x8000; | ||
216 | } | ||
217 | |||
218 | static void pidff_set(struct pidff_usage *usage, u16 value) | ||
219 | { | ||
220 | usage->value[0] = pidff_rescale(value, 0xffff, usage->field); | ||
221 | debug("calculated from %d to %d", value, usage->value[0]); | ||
222 | } | ||
223 | |||
224 | static void pidff_set_signed(struct pidff_usage *usage, s16 value) | ||
225 | { | ||
226 | if (usage->field->logical_minimum < 0) | ||
227 | usage->value[0] = pidff_rescale_signed(value, usage->field); | ||
228 | else { | ||
229 | if (value < 0) | ||
230 | usage->value[0] = | ||
231 | pidff_rescale(-value, 0x8000, usage->field); | ||
232 | else | ||
233 | usage->value[0] = | ||
234 | pidff_rescale(value, 0x7fff, usage->field); | ||
235 | } | ||
236 | debug("calculated from %d to %d", value, usage->value[0]); | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | * Send envelope report to the device | ||
241 | */ | ||
242 | static void pidff_set_envelope_report(struct pidff_device *pidff, | ||
243 | struct ff_envelope *envelope) | ||
244 | { | ||
245 | pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
246 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
247 | |||
248 | pidff->set_envelope[PID_ATTACK_LEVEL].value[0] = | ||
249 | pidff_rescale(envelope->attack_level > | ||
250 | 0x7fff ? 0x7fff : envelope->attack_level, 0x7fff, | ||
251 | pidff->set_envelope[PID_ATTACK_LEVEL].field); | ||
252 | pidff->set_envelope[PID_FADE_LEVEL].value[0] = | ||
253 | pidff_rescale(envelope->fade_level > | ||
254 | 0x7fff ? 0x7fff : envelope->fade_level, 0x7fff, | ||
255 | pidff->set_envelope[PID_FADE_LEVEL].field); | ||
256 | |||
257 | pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length; | ||
258 | pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length; | ||
259 | |||
260 | debug("attack %u => %d", envelope->attack_level, | ||
261 | pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); | ||
262 | |||
263 | hid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], | ||
264 | USB_DIR_OUT); | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * Test if the new envelope differs from old one | ||
269 | */ | ||
270 | static int pidff_needs_set_envelope(struct ff_envelope *envelope, | ||
271 | struct ff_envelope *old) | ||
272 | { | ||
273 | return envelope->attack_level != old->attack_level || | ||
274 | envelope->fade_level != old->fade_level || | ||
275 | envelope->attack_length != old->attack_length || | ||
276 | envelope->fade_length != old->fade_length; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * Send constant force report to the device | ||
281 | */ | ||
282 | static void pidff_set_constant_force_report(struct pidff_device *pidff, | ||
283 | struct ff_effect *effect) | ||
284 | { | ||
285 | pidff->set_constant[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
286 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
287 | pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE], | ||
288 | effect->u.constant.level); | ||
289 | |||
290 | hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT], | ||
291 | USB_DIR_OUT); | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * Test if the constant parameters have changed between effects | ||
296 | */ | ||
297 | static int pidff_needs_set_constant(struct ff_effect *effect, | ||
298 | struct ff_effect *old) | ||
299 | { | ||
300 | return effect->u.constant.level != old->u.constant.level; | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * Send set effect report to the device | ||
305 | */ | ||
306 | static void pidff_set_effect_report(struct pidff_device *pidff, | ||
307 | struct ff_effect *effect) | ||
308 | { | ||
309 | pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
310 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
311 | pidff->set_effect_type->value[0] = | ||
312 | pidff->create_new_effect_type->value[0]; | ||
313 | pidff->set_effect[PID_DURATION].value[0] = effect->replay.length; | ||
314 | pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button; | ||
315 | pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = | ||
316 | effect->trigger.interval; | ||
317 | pidff->set_effect[PID_GAIN].value[0] = | ||
318 | pidff->set_effect[PID_GAIN].field->logical_maximum; | ||
319 | pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; | ||
320 | pidff->effect_direction->value[0] = | ||
321 | pidff_rescale(effect->direction, 0xffff, | ||
322 | pidff->effect_direction); | ||
323 | pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; | ||
324 | |||
325 | hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], | ||
326 | USB_DIR_OUT); | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * Test if the values used in set_effect have changed | ||
331 | */ | ||
332 | static int pidff_needs_set_effect(struct ff_effect *effect, | ||
333 | struct ff_effect *old) | ||
334 | { | ||
335 | return effect->replay.length != old->replay.length || | ||
336 | effect->trigger.interval != old->trigger.interval || | ||
337 | effect->trigger.button != old->trigger.button || | ||
338 | effect->direction != old->direction || | ||
339 | effect->replay.delay != old->replay.delay; | ||
340 | } | ||
341 | |||
342 | /* | ||
343 | * Send periodic effect report to the device | ||
344 | */ | ||
345 | static void pidff_set_periodic_report(struct pidff_device *pidff, | ||
346 | struct ff_effect *effect) | ||
347 | { | ||
348 | pidff->set_periodic[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
349 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
350 | pidff_set_signed(&pidff->set_periodic[PID_MAGNITUDE], | ||
351 | effect->u.periodic.magnitude); | ||
352 | pidff_set_signed(&pidff->set_periodic[PID_OFFSET], | ||
353 | effect->u.periodic.offset); | ||
354 | pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); | ||
355 | pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period; | ||
356 | |||
357 | hid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC], | ||
358 | USB_DIR_OUT); | ||
359 | |||
360 | } | ||
361 | |||
362 | /* | ||
363 | * Test if periodic effect parameters have changed | ||
364 | */ | ||
365 | static int pidff_needs_set_periodic(struct ff_effect *effect, | ||
366 | struct ff_effect *old) | ||
367 | { | ||
368 | return effect->u.periodic.magnitude != old->u.periodic.magnitude || | ||
369 | effect->u.periodic.offset != old->u.periodic.offset || | ||
370 | effect->u.periodic.phase != old->u.periodic.phase || | ||
371 | effect->u.periodic.period != old->u.periodic.period; | ||
372 | } | ||
373 | |||
374 | /* | ||
375 | * Send condition effect reports to the device | ||
376 | */ | ||
377 | static void pidff_set_condition_report(struct pidff_device *pidff, | ||
378 | struct ff_effect *effect) | ||
379 | { | ||
380 | int i; | ||
381 | |||
382 | pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
383 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
384 | |||
385 | for (i = 0; i < 2; i++) { | ||
386 | pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i; | ||
387 | pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET], | ||
388 | effect->u.condition[i].center); | ||
389 | pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT], | ||
390 | effect->u.condition[i].right_coeff); | ||
391 | pidff_set_signed(&pidff->set_condition[PID_NEG_COEFFICIENT], | ||
392 | effect->u.condition[i].left_coeff); | ||
393 | pidff_set(&pidff->set_condition[PID_POS_SATURATION], | ||
394 | effect->u.condition[i].right_saturation); | ||
395 | pidff_set(&pidff->set_condition[PID_NEG_SATURATION], | ||
396 | effect->u.condition[i].left_saturation); | ||
397 | pidff_set(&pidff->set_condition[PID_DEAD_BAND], | ||
398 | effect->u.condition[i].deadband); | ||
399 | hid_wait_io(pidff->hid); | ||
400 | hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION], | ||
401 | USB_DIR_OUT); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | /* | ||
406 | * Test if condition effect parameters have changed | ||
407 | */ | ||
408 | static int pidff_needs_set_condition(struct ff_effect *effect, | ||
409 | struct ff_effect *old) | ||
410 | { | ||
411 | int i; | ||
412 | int ret = 0; | ||
413 | |||
414 | for (i = 0; i < 2; i++) { | ||
415 | struct ff_condition_effect *cond = &effect->u.condition[i]; | ||
416 | struct ff_condition_effect *old_cond = &old->u.condition[i]; | ||
417 | |||
418 | ret |= cond->center != old_cond->center || | ||
419 | cond->right_coeff != old_cond->right_coeff || | ||
420 | cond->left_coeff != old_cond->left_coeff || | ||
421 | cond->right_saturation != old_cond->right_saturation || | ||
422 | cond->left_saturation != old_cond->left_saturation || | ||
423 | cond->deadband != old_cond->deadband; | ||
424 | } | ||
425 | |||
426 | return ret; | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | * Send ramp force report to the device | ||
431 | */ | ||
432 | static void pidff_set_ramp_force_report(struct pidff_device *pidff, | ||
433 | struct ff_effect *effect) | ||
434 | { | ||
435 | pidff->set_ramp[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
436 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
437 | pidff_set_signed(&pidff->set_ramp[PID_RAMP_START], | ||
438 | effect->u.ramp.start_level); | ||
439 | pidff_set_signed(&pidff->set_ramp[PID_RAMP_END], | ||
440 | effect->u.ramp.end_level); | ||
441 | hid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP], | ||
442 | USB_DIR_OUT); | ||
443 | } | ||
444 | |||
445 | /* | ||
446 | * Test if ramp force parameters have changed | ||
447 | */ | ||
448 | static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old) | ||
449 | { | ||
450 | return effect->u.ramp.start_level != old->u.ramp.start_level || | ||
451 | effect->u.ramp.end_level != old->u.ramp.end_level; | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * Send a request for effect upload to the device | ||
456 | * | ||
457 | * Returns 0 if device reported success, -ENOSPC if the device reported memory | ||
458 | * is full. Upon unknown response the function will retry for 60 times, if | ||
459 | * still unsuccessful -EIO is returned. | ||
460 | */ | ||
461 | static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) | ||
462 | { | ||
463 | int j; | ||
464 | |||
465 | pidff->create_new_effect_type->value[0] = efnum; | ||
466 | hid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], | ||
467 | USB_DIR_OUT); | ||
468 | debug("create_new_effect sent, type: %d", efnum); | ||
469 | |||
470 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; | ||
471 | pidff->block_load_status->value[0] = 0; | ||
472 | hid_wait_io(pidff->hid); | ||
473 | |||
474 | for (j = 0; j < 60; j++) { | ||
475 | debug("pid_block_load requested"); | ||
476 | hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], | ||
477 | USB_DIR_IN); | ||
478 | hid_wait_io(pidff->hid); | ||
479 | if (pidff->block_load_status->value[0] == | ||
480 | pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { | ||
481 | debug("device reported free memory: %d bytes", | ||
482 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? | ||
483 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); | ||
484 | return 0; | ||
485 | } | ||
486 | if (pidff->block_load_status->value[0] == | ||
487 | pidff->status_id[PID_BLOCK_LOAD_FULL]) { | ||
488 | debug("not enough memory free: %d bytes", | ||
489 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? | ||
490 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); | ||
491 | return -ENOSPC; | ||
492 | } | ||
493 | } | ||
494 | printk(KERN_ERR "hid-pidff: pid_block_load failed 60 times\n"); | ||
495 | return -EIO; | ||
496 | } | ||
497 | |||
498 | /* | ||
499 | * Play the effect with PID id n times | ||
500 | */ | ||
501 | static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n) | ||
502 | { | ||
503 | pidff->effect_operation[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; | ||
504 | |||
505 | if (n == 0) { | ||
506 | pidff->effect_operation_status->value[0] = | ||
507 | pidff->operation_id[PID_EFFECT_STOP]; | ||
508 | } else { | ||
509 | pidff->effect_operation_status->value[0] = | ||
510 | pidff->operation_id[PID_EFFECT_START]; | ||
511 | pidff->effect_operation[PID_LOOP_COUNT].value[0] = n; | ||
512 | } | ||
513 | |||
514 | hid_wait_io(pidff->hid); | ||
515 | hid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], | ||
516 | USB_DIR_OUT); | ||
517 | } | ||
518 | |||
519 | /** | ||
520 | * Play the effect with effect id @effect_id for @value times | ||
521 | */ | ||
522 | static int pidff_playback(struct input_dev *dev, int effect_id, int value) | ||
523 | { | ||
524 | struct pidff_device *pidff = dev->ff->private; | ||
525 | |||
526 | pidff_playback_pid(pidff, pidff->pid_id[effect_id], value); | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
531 | /* | ||
532 | * Erase effect with PID id | ||
533 | */ | ||
534 | static void pidff_erase_pid(struct pidff_device *pidff, int pid_id) | ||
535 | { | ||
536 | pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; | ||
537 | hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE], | ||
538 | USB_DIR_OUT); | ||
539 | } | ||
540 | |||
541 | /* | ||
542 | * Stop and erase effect with effect_id | ||
543 | */ | ||
544 | static int pidff_erase_effect(struct input_dev *dev, int effect_id) | ||
545 | { | ||
546 | struct pidff_device *pidff = dev->ff->private; | ||
547 | int pid_id = pidff->pid_id[effect_id]; | ||
548 | |||
549 | debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]); | ||
550 | pidff_playback_pid(pidff, pid_id, 0); | ||
551 | pidff_erase_pid(pidff, pid_id); | ||
552 | |||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | /* | ||
557 | * Effect upload handler | ||
558 | */ | ||
559 | static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, | ||
560 | struct ff_effect *old) | ||
561 | { | ||
562 | struct pidff_device *pidff = dev->ff->private; | ||
563 | int type_id; | ||
564 | int error; | ||
565 | |||
566 | switch (effect->type) { | ||
567 | case FF_CONSTANT: | ||
568 | if (!old) { | ||
569 | error = pidff_request_effect_upload(pidff, | ||
570 | pidff->type_id[PID_CONSTANT]); | ||
571 | if (error) | ||
572 | return error; | ||
573 | } | ||
574 | if (!old || pidff_needs_set_effect(effect, old)) | ||
575 | pidff_set_effect_report(pidff, effect); | ||
576 | if (!old || pidff_needs_set_constant(effect, old)) | ||
577 | pidff_set_constant_force_report(pidff, effect); | ||
578 | if (!old || | ||
579 | pidff_needs_set_envelope(&effect->u.constant.envelope, | ||
580 | &old->u.constant.envelope)) | ||
581 | pidff_set_envelope_report(pidff, | ||
582 | &effect->u.constant.envelope); | ||
583 | break; | ||
584 | |||
585 | case FF_PERIODIC: | ||
586 | if (!old) { | ||
587 | switch (effect->u.periodic.waveform) { | ||
588 | case FF_SQUARE: | ||
589 | type_id = PID_SQUARE; | ||
590 | break; | ||
591 | case FF_TRIANGLE: | ||
592 | type_id = PID_TRIANGLE; | ||
593 | break; | ||
594 | case FF_SINE: | ||
595 | type_id = PID_SINE; | ||
596 | break; | ||
597 | case FF_SAW_UP: | ||
598 | type_id = PID_SAW_UP; | ||
599 | break; | ||
600 | case FF_SAW_DOWN: | ||
601 | type_id = PID_SAW_DOWN; | ||
602 | break; | ||
603 | default: | ||
604 | printk(KERN_ERR | ||
605 | "hid-pidff: invalid waveform\n"); | ||
606 | return -EINVAL; | ||
607 | } | ||
608 | |||
609 | error = pidff_request_effect_upload(pidff, | ||
610 | pidff->type_id[type_id]); | ||
611 | if (error) | ||
612 | return error; | ||
613 | } | ||
614 | if (!old || pidff_needs_set_effect(effect, old)) | ||
615 | pidff_set_effect_report(pidff, effect); | ||
616 | if (!old || pidff_needs_set_periodic(effect, old)) | ||
617 | pidff_set_periodic_report(pidff, effect); | ||
618 | if (!old || | ||
619 | pidff_needs_set_envelope(&effect->u.periodic.envelope, | ||
620 | &old->u.periodic.envelope)) | ||
621 | pidff_set_envelope_report(pidff, | ||
622 | &effect->u.periodic.envelope); | ||
623 | break; | ||
624 | |||
625 | case FF_RAMP: | ||
626 | if (!old) { | ||
627 | error = pidff_request_effect_upload(pidff, | ||
628 | pidff->type_id[PID_RAMP]); | ||
629 | if (error) | ||
630 | return error; | ||
631 | } | ||
632 | if (!old || pidff_needs_set_effect(effect, old)) | ||
633 | pidff_set_effect_report(pidff, effect); | ||
634 | if (!old || pidff_needs_set_ramp(effect, old)) | ||
635 | pidff_set_ramp_force_report(pidff, effect); | ||
636 | if (!old || | ||
637 | pidff_needs_set_envelope(&effect->u.ramp.envelope, | ||
638 | &old->u.ramp.envelope)) | ||
639 | pidff_set_envelope_report(pidff, | ||
640 | &effect->u.ramp.envelope); | ||
641 | break; | ||
642 | |||
643 | case FF_SPRING: | ||
644 | if (!old) { | ||
645 | error = pidff_request_effect_upload(pidff, | ||
646 | pidff->type_id[PID_SPRING]); | ||
647 | if (error) | ||
648 | return error; | ||
649 | } | ||
650 | if (!old || pidff_needs_set_effect(effect, old)) | ||
651 | pidff_set_effect_report(pidff, effect); | ||
652 | if (!old || pidff_needs_set_condition(effect, old)) | ||
653 | pidff_set_condition_report(pidff, effect); | ||
654 | break; | ||
655 | |||
656 | case FF_FRICTION: | ||
657 | if (!old) { | ||
658 | error = pidff_request_effect_upload(pidff, | ||
659 | pidff->type_id[PID_FRICTION]); | ||
660 | if (error) | ||
661 | return error; | ||
662 | } | ||
663 | if (!old || pidff_needs_set_effect(effect, old)) | ||
664 | pidff_set_effect_report(pidff, effect); | ||
665 | if (!old || pidff_needs_set_condition(effect, old)) | ||
666 | pidff_set_condition_report(pidff, effect); | ||
667 | break; | ||
668 | |||
669 | case FF_DAMPER: | ||
670 | if (!old) { | ||
671 | error = pidff_request_effect_upload(pidff, | ||
672 | pidff->type_id[PID_DAMPER]); | ||
673 | if (error) | ||
674 | return error; | ||
675 | } | ||
676 | if (!old || pidff_needs_set_effect(effect, old)) | ||
677 | pidff_set_effect_report(pidff, effect); | ||
678 | if (!old || pidff_needs_set_condition(effect, old)) | ||
679 | pidff_set_condition_report(pidff, effect); | ||
680 | break; | ||
681 | |||
682 | case FF_INERTIA: | ||
683 | if (!old) { | ||
684 | error = pidff_request_effect_upload(pidff, | ||
685 | pidff->type_id[PID_INERTIA]); | ||
686 | if (error) | ||
687 | return error; | ||
688 | } | ||
689 | if (!old || pidff_needs_set_effect(effect, old)) | ||
690 | pidff_set_effect_report(pidff, effect); | ||
691 | if (!old || pidff_needs_set_condition(effect, old)) | ||
692 | pidff_set_condition_report(pidff, effect); | ||
693 | break; | ||
694 | |||
695 | default: | ||
696 | printk(KERN_ERR "hid-pidff: invalid type\n"); | ||
697 | return -EINVAL; | ||
698 | } | ||
699 | |||
700 | if (!old) | ||
701 | pidff->pid_id[effect->id] = | ||
702 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
703 | |||
704 | debug("uploaded"); | ||
705 | |||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | /* | ||
710 | * set_gain() handler | ||
711 | */ | ||
712 | static void pidff_set_gain(struct input_dev *dev, u16 gain) | ||
713 | { | ||
714 | struct pidff_device *pidff = dev->ff->private; | ||
715 | |||
716 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); | ||
717 | hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], | ||
718 | USB_DIR_OUT); | ||
719 | } | ||
720 | |||
721 | static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) | ||
722 | { | ||
723 | struct hid_field *field = | ||
724 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field; | ||
725 | |||
726 | if (!magnitude) { | ||
727 | pidff_playback_pid(pidff, field->logical_minimum, 0); | ||
728 | return; | ||
729 | } | ||
730 | |||
731 | pidff_playback_pid(pidff, field->logical_minimum, 1); | ||
732 | |||
733 | pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
734 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum; | ||
735 | pidff->set_effect_type->value[0] = pidff->type_id[PID_SPRING]; | ||
736 | pidff->set_effect[PID_DURATION].value[0] = 0; | ||
737 | pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0; | ||
738 | pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0; | ||
739 | pidff_set(&pidff->set_effect[PID_GAIN], magnitude); | ||
740 | pidff->set_effect[PID_START_DELAY].value[0] = 0; | ||
741 | |||
742 | hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], | ||
743 | USB_DIR_OUT); | ||
744 | } | ||
745 | |||
746 | /* | ||
747 | * pidff_set_autocenter() handler | ||
748 | */ | ||
749 | static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude) | ||
750 | { | ||
751 | struct pidff_device *pidff = dev->ff->private; | ||
752 | |||
753 | pidff_autocenter(pidff, magnitude); | ||
754 | } | ||
755 | |||
756 | /* | ||
757 | * Find fields from a report and fill a pidff_usage | ||
758 | */ | ||
759 | static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, | ||
760 | struct hid_report *report, int count, int strict) | ||
761 | { | ||
762 | int i, j, k, found; | ||
763 | |||
764 | for (k = 0; k < count; k++) { | ||
765 | found = 0; | ||
766 | for (i = 0; i < report->maxfield; i++) { | ||
767 | if (report->field[i]->maxusage != | ||
768 | report->field[i]->report_count) { | ||
769 | debug("maxusage and report_count do not match, " | ||
770 | "skipping"); | ||
771 | continue; | ||
772 | } | ||
773 | for (j = 0; j < report->field[i]->maxusage; j++) { | ||
774 | if (report->field[i]->usage[j].hid == | ||
775 | (HID_UP_PID | table[k])) { | ||
776 | debug("found %d at %d->%d", k, i, j); | ||
777 | usage[k].field = report->field[i]; | ||
778 | usage[k].value = | ||
779 | &report->field[i]->value[j]; | ||
780 | found = 1; | ||
781 | break; | ||
782 | } | ||
783 | } | ||
784 | if (found) | ||
785 | break; | ||
786 | } | ||
787 | if (!found && strict) { | ||
788 | debug("failed to locate %d", k); | ||
789 | return -1; | ||
790 | } | ||
791 | } | ||
792 | return 0; | ||
793 | } | ||
794 | |||
795 | /* | ||
796 | * Return index into pidff_reports for the given usage | ||
797 | */ | ||
798 | static int pidff_check_usage(int usage) | ||
799 | { | ||
800 | int i; | ||
801 | |||
802 | for (i = 0; i < sizeof(pidff_reports); i++) | ||
803 | if (usage == (HID_UP_PID | pidff_reports[i])) | ||
804 | return i; | ||
805 | |||
806 | return -1; | ||
807 | } | ||
808 | |||
809 | /* | ||
810 | * Find the reports and fill pidff->reports[] | ||
811 | * report_type specifies either OUTPUT or FEATURE reports | ||
812 | */ | ||
813 | static void pidff_find_reports(struct hid_device *hid, int report_type, | ||
814 | struct pidff_device *pidff) | ||
815 | { | ||
816 | struct hid_report *report; | ||
817 | int i, ret; | ||
818 | |||
819 | list_for_each_entry(report, | ||
820 | &hid->report_enum[report_type].report_list, list) { | ||
821 | if (report->maxfield < 1) | ||
822 | continue; | ||
823 | ret = pidff_check_usage(report->field[0]->logical); | ||
824 | if (ret != -1) { | ||
825 | debug("found usage 0x%02x from field->logical", | ||
826 | pidff_reports[ret]); | ||
827 | pidff->reports[ret] = report; | ||
828 | continue; | ||
829 | } | ||
830 | |||
831 | /* | ||
832 | * Sometimes logical collections are stacked to indicate | ||
833 | * different usages for the report and the field, in which | ||
834 | * case we want the usage of the parent. However, Linux HID | ||
835 | * implementation hides this fact, so we have to dig it up | ||
836 | * ourselves | ||
837 | */ | ||
838 | i = report->field[0]->usage[0].collection_index; | ||
839 | if (i <= 0 || | ||
840 | hid->collection[i - 1].type != HID_COLLECTION_LOGICAL) | ||
841 | continue; | ||
842 | ret = pidff_check_usage(hid->collection[i - 1].usage); | ||
843 | if (ret != -1 && !pidff->reports[ret]) { | ||
844 | debug("found usage 0x%02x from collection array", | ||
845 | pidff_reports[ret]); | ||
846 | pidff->reports[ret] = report; | ||
847 | } | ||
848 | } | ||
849 | } | ||
850 | |||
851 | /* | ||
852 | * Test if the required reports have been found | ||
853 | */ | ||
854 | static int pidff_reports_ok(struct pidff_device *pidff) | ||
855 | { | ||
856 | int i; | ||
857 | |||
858 | for (i = 0; i <= PID_REQUIRED_REPORTS; i++) { | ||
859 | if (!pidff->reports[i]) { | ||
860 | debug("%d missing", i); | ||
861 | return 0; | ||
862 | } | ||
863 | } | ||
864 | |||
865 | return 1; | ||
866 | } | ||
867 | |||
868 | /* | ||
869 | * Find a field with a specific usage within a report | ||
870 | */ | ||
871 | static struct hid_field *pidff_find_special_field(struct hid_report *report, | ||
872 | int usage, int enforce_min) | ||
873 | { | ||
874 | int i; | ||
875 | |||
876 | for (i = 0; i < report->maxfield; i++) { | ||
877 | if (report->field[i]->logical == (HID_UP_PID | usage) && | ||
878 | report->field[i]->report_count > 0) { | ||
879 | if (!enforce_min || | ||
880 | report->field[i]->logical_minimum == 1) | ||
881 | return report->field[i]; | ||
882 | else { | ||
883 | printk(KERN_ERR "hid-pidff: logical_minimum " | ||
884 | "is not 1 as it should be\n"); | ||
885 | return NULL; | ||
886 | } | ||
887 | } | ||
888 | } | ||
889 | return NULL; | ||
890 | } | ||
891 | |||
892 | /* | ||
893 | * Fill a pidff->*_id struct table | ||
894 | */ | ||
895 | static int pidff_find_special_keys(int *keys, struct hid_field *fld, | ||
896 | const u8 *usagetable, int count) | ||
897 | { | ||
898 | |||
899 | int i, j; | ||
900 | int found = 0; | ||
901 | |||
902 | for (i = 0; i < count; i++) { | ||
903 | for (j = 0; j < fld->maxusage; j++) { | ||
904 | if (fld->usage[j].hid == (HID_UP_PID | usagetable[i])) { | ||
905 | keys[i] = j + 1; | ||
906 | found++; | ||
907 | break; | ||
908 | } | ||
909 | } | ||
910 | } | ||
911 | return found; | ||
912 | } | ||
913 | |||
914 | #define PIDFF_FIND_SPECIAL_KEYS(keys, field, name) \ | ||
915 | pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \ | ||
916 | sizeof(pidff_ ## name)) | ||
917 | |||
918 | /* | ||
919 | * Find and check the special fields | ||
920 | */ | ||
921 | static int pidff_find_special_fields(struct pidff_device *pidff) | ||
922 | { | ||
923 | debug("finding special fields"); | ||
924 | |||
925 | pidff->create_new_effect_type = | ||
926 | pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT], | ||
927 | 0x25, 1); | ||
928 | pidff->set_effect_type = | ||
929 | pidff_find_special_field(pidff->reports[PID_SET_EFFECT], | ||
930 | 0x25, 1); | ||
931 | pidff->effect_direction = | ||
932 | pidff_find_special_field(pidff->reports[PID_SET_EFFECT], | ||
933 | 0x57, 0); | ||
934 | pidff->device_control = | ||
935 | pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL], | ||
936 | 0x96, 1); | ||
937 | pidff->block_load_status = | ||
938 | pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD], | ||
939 | 0x8b, 1); | ||
940 | pidff->effect_operation_status = | ||
941 | pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION], | ||
942 | 0x78, 1); | ||
943 | |||
944 | debug("search done"); | ||
945 | |||
946 | if (!pidff->create_new_effect_type || !pidff->set_effect_type) { | ||
947 | printk(KERN_ERR "hid-pidff: effect lists not found\n"); | ||
948 | return -1; | ||
949 | } | ||
950 | |||
951 | if (!pidff->effect_direction) { | ||
952 | printk(KERN_ERR "hid-pidff: direction field not found\n"); | ||
953 | return -1; | ||
954 | } | ||
955 | |||
956 | if (!pidff->device_control) { | ||
957 | printk(KERN_ERR "hid-pidff: device control field not found\n"); | ||
958 | return -1; | ||
959 | } | ||
960 | |||
961 | if (!pidff->block_load_status) { | ||
962 | printk(KERN_ERR | ||
963 | "hid-pidff: block load status field not found\n"); | ||
964 | return -1; | ||
965 | } | ||
966 | |||
967 | if (!pidff->effect_operation_status) { | ||
968 | printk(KERN_ERR | ||
969 | "hid-pidff: effect operation field not found\n"); | ||
970 | return -1; | ||
971 | } | ||
972 | |||
973 | pidff_find_special_keys(pidff->control_id, pidff->device_control, | ||
974 | pidff_device_control, | ||
975 | sizeof(pidff_device_control)); | ||
976 | |||
977 | PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control); | ||
978 | |||
979 | if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type, | ||
980 | effect_types)) { | ||
981 | printk(KERN_ERR "hid-pidff: no effect types found\n"); | ||
982 | return -1; | ||
983 | } | ||
984 | |||
985 | if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status, | ||
986 | block_load_status) != | ||
987 | sizeof(pidff_block_load_status)) { | ||
988 | printk(KERN_ERR | ||
989 | "hidpidff: block load status identifiers not found\n"); | ||
990 | return -1; | ||
991 | } | ||
992 | |||
993 | if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status, | ||
994 | effect_operation_status) != | ||
995 | sizeof(pidff_effect_operation_status)) { | ||
996 | printk(KERN_ERR | ||
997 | "hidpidff: effect operation identifiers not found\n"); | ||
998 | return -1; | ||
999 | } | ||
1000 | |||
1001 | return 0; | ||
1002 | } | ||
1003 | |||
1004 | /** | ||
1005 | * Find the implemented effect types | ||
1006 | */ | ||
1007 | static int pidff_find_effects(struct pidff_device *pidff, | ||
1008 | struct input_dev *dev) | ||
1009 | { | ||
1010 | int i; | ||
1011 | |||
1012 | for (i = 0; i < sizeof(pidff_effect_types); i++) { | ||
1013 | int pidff_type = pidff->type_id[i]; | ||
1014 | if (pidff->set_effect_type->usage[pidff_type].hid != | ||
1015 | pidff->create_new_effect_type->usage[pidff_type].hid) { | ||
1016 | printk(KERN_ERR "hid-pidff: " | ||
1017 | "effect type number %d is invalid\n", i); | ||
1018 | return -1; | ||
1019 | } | ||
1020 | } | ||
1021 | |||
1022 | if (pidff->type_id[PID_CONSTANT]) | ||
1023 | set_bit(FF_CONSTANT, dev->ffbit); | ||
1024 | if (pidff->type_id[PID_RAMP]) | ||
1025 | set_bit(FF_RAMP, dev->ffbit); | ||
1026 | if (pidff->type_id[PID_SQUARE]) { | ||
1027 | set_bit(FF_SQUARE, dev->ffbit); | ||
1028 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1029 | } | ||
1030 | if (pidff->type_id[PID_SINE]) { | ||
1031 | set_bit(FF_SINE, dev->ffbit); | ||
1032 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1033 | } | ||
1034 | if (pidff->type_id[PID_TRIANGLE]) { | ||
1035 | set_bit(FF_TRIANGLE, dev->ffbit); | ||
1036 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1037 | } | ||
1038 | if (pidff->type_id[PID_SAW_UP]) { | ||
1039 | set_bit(FF_SAW_UP, dev->ffbit); | ||
1040 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1041 | } | ||
1042 | if (pidff->type_id[PID_SAW_DOWN]) { | ||
1043 | set_bit(FF_SAW_DOWN, dev->ffbit); | ||
1044 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1045 | } | ||
1046 | if (pidff->type_id[PID_SPRING]) | ||
1047 | set_bit(FF_SPRING, dev->ffbit); | ||
1048 | if (pidff->type_id[PID_DAMPER]) | ||
1049 | set_bit(FF_DAMPER, dev->ffbit); | ||
1050 | if (pidff->type_id[PID_INERTIA]) | ||
1051 | set_bit(FF_INERTIA, dev->ffbit); | ||
1052 | if (pidff->type_id[PID_FRICTION]) | ||
1053 | set_bit(FF_FRICTION, dev->ffbit); | ||
1054 | |||
1055 | return 0; | ||
1056 | |||
1057 | } | ||
1058 | |||
1059 | #define PIDFF_FIND_FIELDS(name, report, strict) \ | ||
1060 | pidff_find_fields(pidff->name, pidff_ ## name, \ | ||
1061 | pidff->reports[report], \ | ||
1062 | sizeof(pidff_ ## name), strict) | ||
1063 | |||
1064 | /* | ||
1065 | * Fill and check the pidff_usages | ||
1066 | */ | ||
1067 | static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) | ||
1068 | { | ||
1069 | int envelope_ok = 0; | ||
1070 | |||
1071 | if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) { | ||
1072 | printk(KERN_ERR | ||
1073 | "hid-pidff: unknown set_effect report layout\n"); | ||
1074 | return -ENODEV; | ||
1075 | } | ||
1076 | |||
1077 | PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0); | ||
1078 | if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) { | ||
1079 | printk(KERN_ERR | ||
1080 | "hid-pidff: unknown pid_block_load report layout\n"); | ||
1081 | return -ENODEV; | ||
1082 | } | ||
1083 | |||
1084 | if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) { | ||
1085 | printk(KERN_ERR | ||
1086 | "hid-pidff: unknown effect_operation report layout\n"); | ||
1087 | return -ENODEV; | ||
1088 | } | ||
1089 | |||
1090 | if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) { | ||
1091 | printk(KERN_ERR | ||
1092 | "hid-pidff: unknown pid_block_free report layout\n"); | ||
1093 | return -ENODEV; | ||
1094 | } | ||
1095 | |||
1096 | if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) | ||
1097 | envelope_ok = 1; | ||
1098 | |||
1099 | if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev)) | ||
1100 | return -ENODEV; | ||
1101 | |||
1102 | if (!envelope_ok) { | ||
1103 | if (test_and_clear_bit(FF_CONSTANT, dev->ffbit)) | ||
1104 | printk(KERN_WARNING "hid-pidff: " | ||
1105 | "has constant effect but no envelope\n"); | ||
1106 | if (test_and_clear_bit(FF_RAMP, dev->ffbit)) | ||
1107 | printk(KERN_WARNING "hid-pidff: " | ||
1108 | "has ramp effect but no envelope\n"); | ||
1109 | |||
1110 | if (test_and_clear_bit(FF_PERIODIC, dev->ffbit)) | ||
1111 | printk(KERN_WARNING "hid-pidff: " | ||
1112 | "has periodic effect but no envelope\n"); | ||
1113 | } | ||
1114 | |||
1115 | if (test_bit(FF_CONSTANT, dev->ffbit) && | ||
1116 | PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) { | ||
1117 | printk(KERN_WARNING | ||
1118 | "hid-pidff: unknown constant effect layout\n"); | ||
1119 | clear_bit(FF_CONSTANT, dev->ffbit); | ||
1120 | } | ||
1121 | |||
1122 | if (test_bit(FF_RAMP, dev->ffbit) && | ||
1123 | PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) { | ||
1124 | printk(KERN_WARNING "hid-pidff: unknown ramp effect layout\n"); | ||
1125 | clear_bit(FF_RAMP, dev->ffbit); | ||
1126 | } | ||
1127 | |||
1128 | if ((test_bit(FF_SPRING, dev->ffbit) || | ||
1129 | test_bit(FF_DAMPER, dev->ffbit) || | ||
1130 | test_bit(FF_FRICTION, dev->ffbit) || | ||
1131 | test_bit(FF_INERTIA, dev->ffbit)) && | ||
1132 | PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { | ||
1133 | printk(KERN_WARNING | ||
1134 | "hid-pidff: unknown condition effect layout\n"); | ||
1135 | clear_bit(FF_SPRING, dev->ffbit); | ||
1136 | clear_bit(FF_DAMPER, dev->ffbit); | ||
1137 | clear_bit(FF_FRICTION, dev->ffbit); | ||
1138 | clear_bit(FF_INERTIA, dev->ffbit); | ||
1139 | } | ||
1140 | |||
1141 | if (test_bit(FF_PERIODIC, dev->ffbit) && | ||
1142 | PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) { | ||
1143 | printk(KERN_WARNING | ||
1144 | "hid-pidff: unknown periodic effect layout\n"); | ||
1145 | clear_bit(FF_PERIODIC, dev->ffbit); | ||
1146 | } | ||
1147 | |||
1148 | PIDFF_FIND_FIELDS(pool, PID_POOL, 0); | ||
1149 | |||
1150 | if (!PIDFF_FIND_FIELDS(device_gain, PID_DEVICE_GAIN, 1)) | ||
1151 | set_bit(FF_GAIN, dev->ffbit); | ||
1152 | |||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1156 | /* | ||
1157 | * Reset the device | ||
1158 | */ | ||
1159 | static void pidff_reset(struct pidff_device *pidff) | ||
1160 | { | ||
1161 | struct hid_device *hid = pidff->hid; | ||
1162 | int i = 0; | ||
1163 | |||
1164 | pidff->device_control->value[0] = pidff->control_id[PID_RESET]; | ||
1165 | /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ | ||
1166 | hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
1167 | hid_wait_io(hid); | ||
1168 | hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
1169 | hid_wait_io(hid); | ||
1170 | |||
1171 | pidff->device_control->value[0] = | ||
1172 | pidff->control_id[PID_ENABLE_ACTUATORS]; | ||
1173 | hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
1174 | hid_wait_io(hid); | ||
1175 | |||
1176 | /* pool report is sometimes messed up, refetch it */ | ||
1177 | hid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); | ||
1178 | hid_wait_io(hid); | ||
1179 | |||
1180 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { | ||
1181 | int sim_effects = pidff->pool[PID_SIMULTANEOUS_MAX].value[0]; | ||
1182 | while (sim_effects < 2) { | ||
1183 | if (i++ > 20) { | ||
1184 | printk(KERN_WARNING "hid-pidff: device reports " | ||
1185 | "%d simultaneous effects\n", | ||
1186 | sim_effects); | ||
1187 | break; | ||
1188 | } | ||
1189 | debug("pid_pool requested again"); | ||
1190 | hid_submit_report(hid, pidff->reports[PID_POOL], | ||
1191 | USB_DIR_IN); | ||
1192 | hid_wait_io(hid); | ||
1193 | } | ||
1194 | } | ||
1195 | } | ||
1196 | |||
1197 | /* | ||
1198 | * Test if autocenter modification is using the supported method | ||
1199 | */ | ||
1200 | static int pidff_check_autocenter(struct pidff_device *pidff, | ||
1201 | struct input_dev *dev) | ||
1202 | { | ||
1203 | int error; | ||
1204 | |||
1205 | /* | ||
1206 | * Let's find out if autocenter modification is supported | ||
1207 | * Specification doesn't specify anything, so we request an | ||
1208 | * effect upload and cancel it immediately. If the approved | ||
1209 | * effect id was one above the minimum, then we assume the first | ||
1210 | * effect id is a built-in spring type effect used for autocenter | ||
1211 | */ | ||
1212 | |||
1213 | error = pidff_request_effect_upload(pidff, 1); | ||
1214 | if (error) { | ||
1215 | printk(KERN_ERR "hid-pidff: upload request failed\n"); | ||
1216 | return error; | ||
1217 | } | ||
1218 | |||
1219 | if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] == | ||
1220 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) { | ||
1221 | pidff_autocenter(pidff, 0xffff); | ||
1222 | set_bit(FF_AUTOCENTER, dev->ffbit); | ||
1223 | } else { | ||
1224 | printk(KERN_NOTICE "hid-pidff: " | ||
1225 | "device has unknown autocenter control method\n"); | ||
1226 | } | ||
1227 | |||
1228 | pidff_erase_pid(pidff, | ||
1229 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]); | ||
1230 | |||
1231 | return 0; | ||
1232 | |||
1233 | } | ||
1234 | |||
1235 | /* | ||
1236 | * Check if the device is PID and initialize it | ||
1237 | */ | ||
1238 | int hid_pidff_init(struct hid_device *hid) | ||
1239 | { | ||
1240 | struct pidff_device *pidff; | ||
1241 | struct hid_input *hidinput = list_entry(hid->inputs.next, | ||
1242 | struct hid_input, list); | ||
1243 | struct input_dev *dev = hidinput->input; | ||
1244 | struct ff_device *ff; | ||
1245 | int max_effects; | ||
1246 | int error; | ||
1247 | |||
1248 | debug("starting pid init"); | ||
1249 | |||
1250 | if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { | ||
1251 | debug("not a PID device, no output report"); | ||
1252 | return -ENODEV; | ||
1253 | } | ||
1254 | |||
1255 | pidff = kzalloc(sizeof(*pidff), GFP_KERNEL); | ||
1256 | if (!pidff) | ||
1257 | return -ENOMEM; | ||
1258 | |||
1259 | pidff->hid = hid; | ||
1260 | |||
1261 | pidff_find_reports(hid, HID_OUTPUT_REPORT, pidff); | ||
1262 | pidff_find_reports(hid, HID_FEATURE_REPORT, pidff); | ||
1263 | |||
1264 | if (!pidff_reports_ok(pidff)) { | ||
1265 | debug("reports not ok, aborting"); | ||
1266 | error = -ENODEV; | ||
1267 | goto fail; | ||
1268 | } | ||
1269 | |||
1270 | error = pidff_init_fields(pidff, dev); | ||
1271 | if (error) | ||
1272 | goto fail; | ||
1273 | |||
1274 | pidff_reset(pidff); | ||
1275 | |||
1276 | if (test_bit(FF_GAIN, dev->ffbit)) { | ||
1277 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); | ||
1278 | hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], | ||
1279 | USB_DIR_OUT); | ||
1280 | } | ||
1281 | |||
1282 | error = pidff_check_autocenter(pidff, dev); | ||
1283 | if (error) | ||
1284 | goto fail; | ||
1285 | |||
1286 | max_effects = | ||
1287 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum - | ||
1288 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + | ||
1289 | 1; | ||
1290 | debug("max effects is %d", max_effects); | ||
1291 | |||
1292 | if (max_effects > PID_EFFECTS_MAX) | ||
1293 | max_effects = PID_EFFECTS_MAX; | ||
1294 | |||
1295 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) | ||
1296 | debug("max simultaneous effects is %d", | ||
1297 | pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); | ||
1298 | |||
1299 | if (pidff->pool[PID_RAM_POOL_SIZE].value) | ||
1300 | debug("device memory size is %d bytes", | ||
1301 | pidff->pool[PID_RAM_POOL_SIZE].value[0]); | ||
1302 | |||
1303 | if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && | ||
1304 | pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { | ||
1305 | printk(KERN_NOTICE "hid-pidff: " | ||
1306 | "device does not support device managed pool\n"); | ||
1307 | goto fail; | ||
1308 | } | ||
1309 | |||
1310 | error = input_ff_create(dev, max_effects); | ||
1311 | if (error) | ||
1312 | goto fail; | ||
1313 | |||
1314 | ff = dev->ff; | ||
1315 | ff->private = pidff; | ||
1316 | ff->upload = pidff_upload_effect; | ||
1317 | ff->erase = pidff_erase_effect; | ||
1318 | ff->set_gain = pidff_set_gain; | ||
1319 | ff->set_autocenter = pidff_set_autocenter; | ||
1320 | ff->playback = pidff_playback; | ||
1321 | |||
1322 | printk(KERN_INFO "Force feedback for USB HID PID devices by " | ||
1323 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
1324 | |||
1325 | return 0; | ||
1326 | |||
1327 | fail: | ||
1328 | kfree(pidff); | ||
1329 | return error; | ||
1330 | } | ||
diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c index 534425c69c0a..2d5be4c318ac 100644 --- a/drivers/usb/input/hid-tmff.c +++ b/drivers/usb/input/hid-tmff.c | |||
@@ -28,97 +28,65 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/input.h> | 30 | #include <linux/input.h> |
31 | #include <linux/sched.h> | ||
32 | 31 | ||
33 | #undef DEBUG | 32 | #undef DEBUG |
34 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
35 | 34 | ||
36 | #include <linux/circ_buf.h> | ||
37 | |||
38 | #include "hid.h" | 35 | #include "hid.h" |
39 | #include "fixp-arith.h" | ||
40 | 36 | ||
41 | /* Usages for thrustmaster devices I know about */ | 37 | /* Usages for thrustmaster devices I know about */ |
42 | #define THRUSTMASTER_USAGE_RUMBLE_LR (HID_UP_GENDESK | 0xbb) | 38 | #define THRUSTMASTER_USAGE_RUMBLE_LR (HID_UP_GENDESK | 0xbb) |
43 | #define DELAY_CALC(t,delay) ((t) + (delay)*HZ/1000) | ||
44 | |||
45 | /* Effect status */ | ||
46 | #define EFFECT_STARTED 0 /* Effect is going to play after some time */ | ||
47 | #define EFFECT_PLAYING 1 /* Effect is playing */ | ||
48 | #define EFFECT_USED 2 | ||
49 | |||
50 | /* For tmff_device::flags */ | ||
51 | #define DEVICE_CLOSING 0 /* The driver is being unitialised */ | ||
52 | |||
53 | /* Check that the current process can access an effect */ | ||
54 | #define CHECK_OWNERSHIP(effect) (current->pid == 0 \ | ||
55 | || effect.owner == current->pid) | ||
56 | |||
57 | #define TMFF_CHECK_ID(id) ((id) >= 0 && (id) < TMFF_EFFECTS) | ||
58 | 39 | ||
59 | #define TMFF_CHECK_OWNERSHIP(i, l) \ | ||
60 | (test_bit(EFFECT_USED, l->effects[i].flags) \ | ||
61 | && CHECK_OWNERSHIP(l->effects[i])) | ||
62 | |||
63 | #define TMFF_EFFECTS 8 | ||
64 | |||
65 | struct tmff_effect { | ||
66 | pid_t owner; | ||
67 | |||
68 | struct ff_effect effect; | ||
69 | |||
70 | unsigned long flags[1]; | ||
71 | unsigned int count; /* Number of times left to play */ | ||
72 | |||
73 | unsigned long play_at; /* When the effect starts to play */ | ||
74 | unsigned long stop_at; /* When the effect ends */ | ||
75 | }; | ||
76 | 40 | ||
77 | struct tmff_device { | 41 | struct tmff_device { |
78 | struct hid_device *hid; | ||
79 | |||
80 | struct hid_report *report; | 42 | struct hid_report *report; |
81 | |||
82 | struct hid_field *rumble; | 43 | struct hid_field *rumble; |
44 | }; | ||
83 | 45 | ||
84 | unsigned int effects_playing; | 46 | /* Changes values from 0 to 0xffff into values from minimum to maximum */ |
85 | struct tmff_effect effects[TMFF_EFFECTS]; | 47 | static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum) |
86 | spinlock_t lock; /* device-level lock. Having locks on | 48 | { |
87 | a per-effect basis could be nice, but | 49 | int ret; |
88 | isn't really necessary */ | ||
89 | 50 | ||
90 | unsigned long flags[1]; /* Contains various information about the | 51 | ret = (in * (maximum - minimum) / 0xffff) + minimum; |
91 | state of the driver for this device */ | 52 | if (ret < minimum) |
53 | return minimum; | ||
54 | if (ret > maximum) | ||
55 | return maximum; | ||
56 | return ret; | ||
57 | } | ||
92 | 58 | ||
93 | struct timer_list timer; | 59 | static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect) |
94 | }; | 60 | { |
61 | struct hid_device *hid = dev->private; | ||
62 | struct tmff_device *tmff = data; | ||
63 | int left, right; /* Rumbling */ | ||
95 | 64 | ||
96 | /* Callbacks */ | 65 | left = hid_tmff_scale(effect->u.rumble.weak_magnitude, |
97 | static void hid_tmff_exit(struct hid_device *hid); | 66 | tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); |
98 | static int hid_tmff_event(struct hid_device *hid, struct input_dev *input, | 67 | right = hid_tmff_scale(effect->u.rumble.strong_magnitude, |
99 | unsigned int type, unsigned int code, int value); | 68 | tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); |
100 | static int hid_tmff_flush(struct input_dev *input, struct file *file); | ||
101 | static int hid_tmff_upload_effect(struct input_dev *input, | ||
102 | struct ff_effect *effect); | ||
103 | static int hid_tmff_erase(struct input_dev *input, int id); | ||
104 | 69 | ||
105 | /* Local functions */ | 70 | tmff->rumble->value[0] = left; |
106 | static void hid_tmff_recalculate_timer(struct tmff_device *tmff); | 71 | tmff->rumble->value[1] = right; |
107 | static void hid_tmff_timer(unsigned long timer_data); | 72 | dbg("(left,right)=(%08x, %08x)", left, right); |
73 | hid_submit_report(hid, tmff->report, USB_DIR_OUT); | ||
74 | |||
75 | return 0; | ||
76 | } | ||
108 | 77 | ||
109 | int hid_tmff_init(struct hid_device *hid) | 78 | int hid_tmff_init(struct hid_device *hid) |
110 | { | 79 | { |
111 | struct tmff_device *private; | 80 | struct tmff_device *tmff; |
112 | struct list_head *pos; | 81 | struct list_head *pos; |
113 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | 82 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); |
114 | struct input_dev *input_dev = hidinput->input; | 83 | struct input_dev *input_dev = hidinput->input; |
84 | int error; | ||
115 | 85 | ||
116 | private = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); | 86 | tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); |
117 | if (!private) | 87 | if (!tmff) |
118 | return -ENOMEM; | 88 | return -ENOMEM; |
119 | 89 | ||
120 | hid->ff_private = private; | ||
121 | |||
122 | /* Find the report to use */ | 90 | /* Find the report to use */ |
123 | __list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) { | 91 | __list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) { |
124 | struct hid_report *report = (struct hid_report *)pos; | 92 | struct hid_report *report = (struct hid_report *)pos; |
@@ -142,18 +110,18 @@ int hid_tmff_init(struct hid_device *hid) | |||
142 | continue; | 110 | continue; |
143 | } | 111 | } |
144 | 112 | ||
145 | if (private->report && private->report != report) { | 113 | if (tmff->report && tmff->report != report) { |
146 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR in other report"); | 114 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR in other report"); |
147 | continue; | 115 | continue; |
148 | } | 116 | } |
149 | 117 | ||
150 | if (private->rumble && private->rumble != field) { | 118 | if (tmff->rumble && tmff->rumble != field) { |
151 | warn("ignoring duplicate THRUSTMASTER_USAGE_RUMBLE_LR"); | 119 | warn("ignoring duplicate THRUSTMASTER_USAGE_RUMBLE_LR"); |
152 | continue; | 120 | continue; |
153 | } | 121 | } |
154 | 122 | ||
155 | private->report = report; | 123 | tmff->report = report; |
156 | private->rumble = field; | 124 | tmff->rumble = field; |
157 | 125 | ||
158 | set_bit(FF_RUMBLE, input_dev->ffbit); | 126 | set_bit(FF_RUMBLE, input_dev->ffbit); |
159 | break; | 127 | break; |
@@ -162,302 +130,17 @@ int hid_tmff_init(struct hid_device *hid) | |||
162 | warn("ignoring unknown output usage %08x", field->usage[0].hid); | 130 | warn("ignoring unknown output usage %08x", field->usage[0].hid); |
163 | continue; | 131 | continue; |
164 | } | 132 | } |
165 | |||
166 | /* Fallthrough to here only when a valid usage is found */ | ||
167 | input_dev->upload_effect = hid_tmff_upload_effect; | ||
168 | input_dev->flush = hid_tmff_flush; | ||
169 | |||
170 | set_bit(EV_FF, input_dev->evbit); | ||
171 | input_dev->ff_effects_max = TMFF_EFFECTS; | ||
172 | } | 133 | } |
173 | } | 134 | } |
174 | 135 | ||
175 | private->hid = hid; | 136 | error = input_ff_create_memless(input_dev, tmff, hid_tmff_play); |
176 | 137 | if (error) { | |
177 | spin_lock_init(&private->lock); | 138 | kfree(tmff); |
178 | init_timer(&private->timer); | 139 | return error; |
179 | private->timer.data = (unsigned long)private; | ||
180 | private->timer.function = hid_tmff_timer; | ||
181 | |||
182 | /* Event and exit callbacks */ | ||
183 | hid->ff_exit = hid_tmff_exit; | ||
184 | hid->ff_event = hid_tmff_event; | ||
185 | |||
186 | info("Force feedback for ThrustMaster rumble pad devices by Zinx Verituse <zinx@epicsol.org>"); | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static void hid_tmff_exit(struct hid_device *hid) | ||
192 | { | ||
193 | struct tmff_device *tmff = hid->ff_private; | ||
194 | unsigned long flags; | ||
195 | |||
196 | spin_lock_irqsave(&tmff->lock, flags); | ||
197 | |||
198 | set_bit(DEVICE_CLOSING, tmff->flags); | ||
199 | del_timer_sync(&tmff->timer); | ||
200 | |||
201 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
202 | |||
203 | kfree(tmff); | ||
204 | } | ||
205 | |||
206 | static int hid_tmff_event(struct hid_device *hid, struct input_dev *input, | ||
207 | unsigned int type, unsigned int code, int value) | ||
208 | { | ||
209 | struct tmff_device *tmff = hid->ff_private; | ||
210 | struct tmff_effect *effect = &tmff->effects[code]; | ||
211 | unsigned long flags; | ||
212 | |||
213 | if (type != EV_FF) | ||
214 | return -EINVAL; | ||
215 | if (!TMFF_CHECK_ID(code)) | ||
216 | return -EINVAL; | ||
217 | if (!TMFF_CHECK_OWNERSHIP(code, tmff)) | ||
218 | return -EACCES; | ||
219 | if (value < 0) | ||
220 | return -EINVAL; | ||
221 | |||
222 | spin_lock_irqsave(&tmff->lock, flags); | ||
223 | |||
224 | if (value > 0) { | ||
225 | set_bit(EFFECT_STARTED, effect->flags); | ||
226 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
227 | effect->count = value; | ||
228 | effect->play_at = DELAY_CALC(jiffies, effect->effect.replay.delay); | ||
229 | } else { | ||
230 | clear_bit(EFFECT_STARTED, effect->flags); | ||
231 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
232 | } | ||
233 | |||
234 | hid_tmff_recalculate_timer(tmff); | ||
235 | |||
236 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
237 | |||
238 | return 0; | ||
239 | |||
240 | } | ||
241 | |||
242 | /* Erase all effects this process owns */ | ||
243 | |||
244 | static int hid_tmff_flush(struct input_dev *dev, struct file *file) | ||
245 | { | ||
246 | struct hid_device *hid = dev->private; | ||
247 | struct tmff_device *tmff = hid->ff_private; | ||
248 | int i; | ||
249 | |||
250 | for (i=0; i<dev->ff_effects_max; ++i) | ||
251 | |||
252 | /* NOTE: no need to lock here. The only times EFFECT_USED is | ||
253 | modified is when effects are uploaded or when an effect is | ||
254 | erased. But a process cannot close its dev/input/eventX fd | ||
255 | and perform ioctls on the same fd all at the same time */ | ||
256 | |||
257 | if (current->pid == tmff->effects[i].owner | ||
258 | && test_bit(EFFECT_USED, tmff->effects[i].flags)) | ||
259 | if (hid_tmff_erase(dev, i)) | ||
260 | warn("erase effect %d failed", i); | ||
261 | |||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int hid_tmff_erase(struct input_dev *dev, int id) | ||
267 | { | ||
268 | struct hid_device *hid = dev->private; | ||
269 | struct tmff_device *tmff = hid->ff_private; | ||
270 | unsigned long flags; | ||
271 | |||
272 | if (!TMFF_CHECK_ID(id)) | ||
273 | return -EINVAL; | ||
274 | if (!TMFF_CHECK_OWNERSHIP(id, tmff)) | ||
275 | return -EACCES; | ||
276 | |||
277 | spin_lock_irqsave(&tmff->lock, flags); | ||
278 | |||
279 | tmff->effects[id].flags[0] = 0; | ||
280 | hid_tmff_recalculate_timer(tmff); | ||
281 | |||
282 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static int hid_tmff_upload_effect(struct input_dev *input, | ||
288 | struct ff_effect *effect) | ||
289 | { | ||
290 | struct hid_device *hid = input->private; | ||
291 | struct tmff_device *tmff = hid->ff_private; | ||
292 | int id; | ||
293 | unsigned long flags; | ||
294 | |||
295 | if (!test_bit(effect->type, input->ffbit)) | ||
296 | return -EINVAL; | ||
297 | if (effect->id != -1 && !TMFF_CHECK_ID(effect->id)) | ||
298 | return -EINVAL; | ||
299 | |||
300 | spin_lock_irqsave(&tmff->lock, flags); | ||
301 | |||
302 | if (effect->id == -1) { | ||
303 | /* Find a free effect */ | ||
304 | for (id = 0; id < TMFF_EFFECTS && test_bit(EFFECT_USED, tmff->effects[id].flags); ++id); | ||
305 | |||
306 | if (id >= TMFF_EFFECTS) { | ||
307 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
308 | return -ENOSPC; | ||
309 | } | ||
310 | |||
311 | effect->id = id; | ||
312 | tmff->effects[id].owner = current->pid; | ||
313 | tmff->effects[id].flags[0] = 0; | ||
314 | set_bit(EFFECT_USED, tmff->effects[id].flags); | ||
315 | |||
316 | } else { | ||
317 | /* Re-uploading an owned effect, to change parameters */ | ||
318 | id = effect->id; | ||
319 | clear_bit(EFFECT_PLAYING, tmff->effects[id].flags); | ||
320 | } | 140 | } |
321 | 141 | ||
322 | tmff->effects[id].effect = *effect; | 142 | info("Force feedback for ThrustMaster rumble pad devices by Zinx Verituse <zinx@epicsol.org>"); |
323 | |||
324 | hid_tmff_recalculate_timer(tmff); | ||
325 | 143 | ||
326 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
327 | return 0; | 144 | return 0; |
328 | } | 145 | } |
329 | 146 | ||
330 | /* Start the timer for the next start/stop/delay */ | ||
331 | /* Always call this while tmff->lock is locked */ | ||
332 | |||
333 | static void hid_tmff_recalculate_timer(struct tmff_device *tmff) | ||
334 | { | ||
335 | int i; | ||
336 | int events = 0; | ||
337 | unsigned long next_time; | ||
338 | |||
339 | next_time = 0; /* Shut up compiler's incorrect warning */ | ||
340 | |||
341 | /* Find the next change in an effect's status */ | ||
342 | for (i = 0; i < TMFF_EFFECTS; ++i) { | ||
343 | struct tmff_effect *effect = &tmff->effects[i]; | ||
344 | unsigned long play_time; | ||
345 | |||
346 | if (!test_bit(EFFECT_STARTED, effect->flags)) | ||
347 | continue; | ||
348 | |||
349 | effect->stop_at = DELAY_CALC(effect->play_at, effect->effect.replay.length); | ||
350 | |||
351 | if (!test_bit(EFFECT_PLAYING, effect->flags)) | ||
352 | play_time = effect->play_at; | ||
353 | else | ||
354 | play_time = effect->stop_at; | ||
355 | |||
356 | events++; | ||
357 | |||
358 | if (time_after(jiffies, play_time)) | ||
359 | play_time = jiffies; | ||
360 | |||
361 | if (events == 1) | ||
362 | next_time = play_time; | ||
363 | else { | ||
364 | if (time_after(next_time, play_time)) | ||
365 | next_time = play_time; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | if (!events && tmff->effects_playing) { | ||
370 | /* Treat all effects turning off as an event */ | ||
371 | events = 1; | ||
372 | next_time = jiffies; | ||
373 | } | ||
374 | |||
375 | if (!events) { | ||
376 | /* No events, no time, no need for a timer. */ | ||
377 | del_timer_sync(&tmff->timer); | ||
378 | return; | ||
379 | } | ||
380 | |||
381 | mod_timer(&tmff->timer, next_time); | ||
382 | } | ||
383 | |||
384 | /* Changes values from 0 to 0xffff into values from minimum to maximum */ | ||
385 | static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum) | ||
386 | { | ||
387 | int ret; | ||
388 | |||
389 | ret = (in * (maximum - minimum) / 0xffff) + minimum; | ||
390 | if (ret < minimum) | ||
391 | return minimum; | ||
392 | if (ret > maximum) | ||
393 | return maximum; | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | static void hid_tmff_timer(unsigned long timer_data) | ||
398 | { | ||
399 | struct tmff_device *tmff = (struct tmff_device *) timer_data; | ||
400 | struct hid_device *hid = tmff->hid; | ||
401 | unsigned long flags; | ||
402 | int left = 0, right = 0; /* Rumbling */ | ||
403 | int i; | ||
404 | |||
405 | spin_lock_irqsave(&tmff->lock, flags); | ||
406 | |||
407 | tmff->effects_playing = 0; | ||
408 | |||
409 | for (i = 0; i < TMFF_EFFECTS; ++i) { | ||
410 | struct tmff_effect *effect = &tmff->effects[i]; | ||
411 | |||
412 | if (!test_bit(EFFECT_STARTED, effect->flags)) | ||
413 | continue; | ||
414 | |||
415 | if (!time_after(jiffies, effect->play_at)) | ||
416 | continue; | ||
417 | |||
418 | if (time_after(jiffies, effect->stop_at)) { | ||
419 | |||
420 | dbg("Finished playing once %d", i); | ||
421 | clear_bit(EFFECT_PLAYING, effect->flags); | ||
422 | |||
423 | if (--effect->count <= 0) { | ||
424 | dbg("Stopped %d", i); | ||
425 | clear_bit(EFFECT_STARTED, effect->flags); | ||
426 | continue; | ||
427 | } else { | ||
428 | dbg("Start again %d", i); | ||
429 | effect->play_at = DELAY_CALC(jiffies, effect->effect.replay.delay); | ||
430 | continue; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | ++tmff->effects_playing; | ||
435 | |||
436 | set_bit(EFFECT_PLAYING, effect->flags); | ||
437 | |||
438 | switch (effect->effect.type) { | ||
439 | case FF_RUMBLE: | ||
440 | right += effect->effect.u.rumble.strong_magnitude; | ||
441 | left += effect->effect.u.rumble.weak_magnitude; | ||
442 | break; | ||
443 | default: | ||
444 | BUG(); | ||
445 | break; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | left = hid_tmff_scale(left, tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); | ||
450 | right = hid_tmff_scale(right, tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); | ||
451 | |||
452 | if (left != tmff->rumble->value[0] || right != tmff->rumble->value[1]) { | ||
453 | tmff->rumble->value[0] = left; | ||
454 | tmff->rumble->value[1] = right; | ||
455 | dbg("(left,right)=(%08x, %08x)", left, right); | ||
456 | hid_submit_report(hid, tmff->report, USB_DIR_OUT); | ||
457 | } | ||
458 | |||
459 | if (!test_bit(DEVICE_CLOSING, tmff->flags)) | ||
460 | hid_tmff_recalculate_timer(tmff); | ||
461 | |||
462 | spin_unlock_irqrestore(&tmff->lock, flags); | ||
463 | } | ||
diff --git a/drivers/usb/input/hid-zpff.c b/drivers/usb/input/hid-zpff.c new file mode 100644 index 000000000000..d2ce3214572c --- /dev/null +++ b/drivers/usb/input/hid-zpff.c | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * Force feedback support for Zeroplus based devices | ||
3 | * | ||
4 | * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
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 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* #define DEBUG */ | ||
25 | |||
26 | #define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg) | ||
27 | |||
28 | #include <linux/input.h> | ||
29 | #include <linux/usb.h> | ||
30 | #include "hid.h" | ||
31 | |||
32 | struct zpff_device { | ||
33 | struct hid_report *report; | ||
34 | }; | ||
35 | |||
36 | static int hid_zpff_play(struct input_dev *dev, void *data, | ||
37 | struct ff_effect *effect) | ||
38 | { | ||
39 | struct hid_device *hid = dev->private; | ||
40 | struct zpff_device *zpff = data; | ||
41 | int left, right; | ||
42 | |||
43 | /* | ||
44 | * The following is specified the other way around in the Zeroplus | ||
45 | * datasheet but the order below is correct for the XFX Executioner; | ||
46 | * however it is possible that the XFX Executioner is an exception | ||
47 | */ | ||
48 | |||
49 | left = effect->u.rumble.strong_magnitude; | ||
50 | right = effect->u.rumble.weak_magnitude; | ||
51 | debug("called with 0x%04x 0x%04x", left, right); | ||
52 | |||
53 | left = left * 0x7f / 0xffff; | ||
54 | right = right * 0x7f / 0xffff; | ||
55 | |||
56 | zpff->report->field[2]->value[0] = left; | ||
57 | zpff->report->field[3]->value[0] = right; | ||
58 | debug("running with 0x%02x 0x%02x", left, right); | ||
59 | hid_submit_report(hid, zpff->report, USB_DIR_OUT); | ||
60 | |||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | int hid_zpff_init(struct hid_device *hid) | ||
65 | { | ||
66 | struct zpff_device *zpff; | ||
67 | struct hid_report *report; | ||
68 | struct hid_input *hidinput = list_entry(hid->inputs.next, | ||
69 | struct hid_input, list); | ||
70 | struct list_head *report_list = | ||
71 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
72 | struct input_dev *dev = hidinput->input; | ||
73 | int error; | ||
74 | |||
75 | if (list_empty(report_list)) { | ||
76 | printk(KERN_ERR "hid-zpff: no output report found\n"); | ||
77 | return -ENODEV; | ||
78 | } | ||
79 | |||
80 | report = list_entry(report_list->next, struct hid_report, list); | ||
81 | |||
82 | if (report->maxfield < 4) { | ||
83 | printk(KERN_ERR "hid-zpff: not enough fields in report\n"); | ||
84 | return -ENODEV; | ||
85 | } | ||
86 | |||
87 | zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); | ||
88 | if (!zpff) | ||
89 | return -ENOMEM; | ||
90 | |||
91 | set_bit(FF_RUMBLE, dev->ffbit); | ||
92 | |||
93 | error = input_ff_create_memless(dev, zpff, hid_zpff_play); | ||
94 | if (error) { | ||
95 | kfree(zpff); | ||
96 | return error; | ||
97 | } | ||
98 | |||
99 | zpff->report = report; | ||
100 | zpff->report->field[0]->value[0] = 0x00; | ||
101 | zpff->report->field[1]->value[0] = 0x02; | ||
102 | zpff->report->field[2]->value[0] = 0x00; | ||
103 | zpff->report->field[3]->value[0] = 0x00; | ||
104 | hid_submit_report(hid, zpff->report, USB_DIR_OUT); | ||
105 | |||
106 | printk(KERN_INFO "Force feedback for Zeroplus based devices by " | ||
107 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 778e575de352..b03fd9b075df 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h | |||
@@ -449,11 +449,6 @@ struct hid_device { /* device report descriptor */ | |||
449 | char phys[64]; /* Device physical location */ | 449 | char phys[64]; /* Device physical location */ |
450 | char uniq[64]; /* Device unique identifier (serial #) */ | 450 | char uniq[64]; /* Device unique identifier (serial #) */ |
451 | 451 | ||
452 | void *ff_private; /* Private data for the force-feedback driver */ | ||
453 | void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ | ||
454 | int (*ff_event)(struct hid_device *hid, struct input_dev *input, | ||
455 | unsigned int type, unsigned int code, int value); | ||
456 | |||
457 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | 452 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK |
458 | unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; | 453 | unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; |
459 | unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; | 454 | unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; |
@@ -521,29 +516,22 @@ void hid_close(struct hid_device *); | |||
521 | int hid_set_field(struct hid_field *, unsigned, __s32); | 516 | int hid_set_field(struct hid_field *, unsigned, __s32); |
522 | void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir); | 517 | void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir); |
523 | void hid_init_reports(struct hid_device *hid); | 518 | void hid_init_reports(struct hid_device *hid); |
524 | struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type); | ||
525 | int hid_wait_io(struct hid_device* hid); | 519 | int hid_wait_io(struct hid_device* hid); |
526 | 520 | ||
527 | 521 | ||
528 | #ifdef CONFIG_HID_FF | 522 | #ifdef CONFIG_HID_FF |
529 | int hid_ff_init(struct hid_device *hid); | 523 | int hid_ff_init(struct hid_device *hid); |
524 | |||
525 | int hid_lgff_init(struct hid_device *hid); | ||
526 | int hid_tmff_init(struct hid_device *hid); | ||
527 | int hid_zpff_init(struct hid_device *hid); | ||
528 | #ifdef CONFIG_HID_PID | ||
529 | int hid_pidff_init(struct hid_device *hid); | ||
530 | #else | ||
531 | static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; } | ||
532 | #endif | ||
533 | |||
530 | #else | 534 | #else |
531 | static inline int hid_ff_init(struct hid_device *hid) { return -1; } | 535 | static inline int hid_ff_init(struct hid_device *hid) { return -1; } |
532 | #endif | 536 | #endif |
533 | static inline void hid_ff_exit(struct hid_device *hid) | ||
534 | { | ||
535 | if (hid->ff_exit) | ||
536 | hid->ff_exit(hid); | ||
537 | } | ||
538 | static inline int hid_ff_event(struct hid_device *hid, struct input_dev *input, | ||
539 | unsigned int type, unsigned int code, int value) | ||
540 | { | ||
541 | if (hid->ff_event) | ||
542 | return hid->ff_event(hid, input, type, code, value); | ||
543 | return -ENOSYS; | ||
544 | } | ||
545 | |||
546 | int hid_lgff_init(struct hid_device* hid); | ||
547 | int hid_tmff_init(struct hid_device* hid); | ||
548 | int hid_pid_init(struct hid_device* hid); | ||
549 | 537 | ||
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c deleted file mode 100644 index d9d9f656b8c9..000000000000 --- a/drivers/usb/input/pid.c +++ /dev/null | |||
@@ -1,295 +0,0 @@ | |||
1 | /* | ||
2 | * PID Force feedback support for hid devices. | ||
3 | * | ||
4 | * Copyright (c) 2002 Rodrigo Damazio. | ||
5 | * Portions by Johann Deneux and Bjorn Augustson | ||
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 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | * Should you need to contact me, the author, you can do so by | ||
24 | * e-mail - mail your message to <rdamazio@lsi.usp.br> | ||
25 | */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/mm.h> | ||
33 | #include <linux/smp_lock.h> | ||
34 | #include <linux/spinlock.h> | ||
35 | #include <linux/input.h> | ||
36 | #include <linux/usb.h> | ||
37 | #include "hid.h" | ||
38 | #include "pid.h" | ||
39 | |||
40 | #define CHECK_OWNERSHIP(i, hid_pid) \ | ||
41 | ((i) < FF_EFFECTS_MAX && i >= 0 && \ | ||
42 | test_bit(FF_PID_FLAGS_USED, &hid_pid->effects[(i)].flags) && \ | ||
43 | (current->pid == 0 || \ | ||
44 | (hid_pid)->effects[(i)].owner == current->pid)) | ||
45 | |||
46 | /* Called when a transfer is completed */ | ||
47 | static void hid_pid_ctrl_out(struct urb *u, struct pt_regs *regs) | ||
48 | { | ||
49 | dev_dbg(&u->dev->dev, "hid_pid_ctrl_out - Transfer Completed\n"); | ||
50 | } | ||
51 | |||
52 | static void hid_pid_exit(struct hid_device *hid) | ||
53 | { | ||
54 | struct hid_ff_pid *private = hid->ff_private; | ||
55 | |||
56 | if (private->urbffout) { | ||
57 | usb_kill_urb(private->urbffout); | ||
58 | usb_free_urb(private->urbffout); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | static int pid_upload_periodic(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) | ||
63 | { | ||
64 | dev_info(&pid->hid->dev->dev, "requested periodic force upload\n"); | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int pid_upload_constant(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) | ||
69 | { | ||
70 | dev_info(&pid->hid->dev->dev, "requested constant force upload\n"); | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int pid_upload_condition(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) | ||
75 | { | ||
76 | dev_info(&pid->hid->dev->dev, "requested Condition force upload\n"); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int pid_upload_ramp(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) | ||
81 | { | ||
82 | dev_info(&pid->hid->dev->dev, "request ramp force upload\n"); | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int hid_pid_event(struct hid_device *hid, struct input_dev *input, | ||
87 | unsigned int type, unsigned int code, int value) | ||
88 | { | ||
89 | dev_dbg(&hid->dev->dev, "PID event received: type=%d,code=%d,value=%d.\n", type, code, value); | ||
90 | |||
91 | if (type != EV_FF) | ||
92 | return -1; | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | /* Lock must be held by caller */ | ||
98 | static void hid_pid_ctrl_playback(struct hid_device *hid, struct hid_pid_effect *effect, int play) | ||
99 | { | ||
100 | if (play) | ||
101 | set_bit(FF_PID_FLAGS_PLAYING, &effect->flags); | ||
102 | else | ||
103 | clear_bit(FF_PID_FLAGS_PLAYING, &effect->flags); | ||
104 | } | ||
105 | |||
106 | static int hid_pid_erase(struct input_dev *dev, int id) | ||
107 | { | ||
108 | struct hid_device *hid = dev->private; | ||
109 | struct hid_ff_pid *pid = hid->ff_private; | ||
110 | struct hid_field *field; | ||
111 | unsigned long flags; | ||
112 | int ret; | ||
113 | |||
114 | if (!CHECK_OWNERSHIP(id, pid)) | ||
115 | return -EACCES; | ||
116 | |||
117 | /* Find report */ | ||
118 | field = hid_find_field_by_usage(hid, HID_UP_PID | FF_PID_USAGE_BLOCK_FREE, | ||
119 | HID_OUTPUT_REPORT); | ||
120 | if (!field) { | ||
121 | dev_err(&hid->dev->dev, "couldn't find report\n"); | ||
122 | return -EIO; | ||
123 | } | ||
124 | |||
125 | ret = hid_set_field(field, 0, pid->effects[id].device_id); | ||
126 | if (ret) { | ||
127 | dev_err(&hid->dev->dev, "couldn't set field\n"); | ||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | hid_submit_report(hid, field->report, USB_DIR_OUT); | ||
132 | |||
133 | spin_lock_irqsave(&pid->lock, flags); | ||
134 | hid_pid_ctrl_playback(hid, pid->effects + id, 0); | ||
135 | pid->effects[id].flags = 0; | ||
136 | spin_unlock_irqrestore(&pid->lock, flags); | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | /* Erase all effects this process owns */ | ||
142 | static int hid_pid_flush(struct input_dev *dev, struct file *file) | ||
143 | { | ||
144 | struct hid_device *hid = dev->private; | ||
145 | struct hid_ff_pid *pid = hid->ff_private; | ||
146 | int i; | ||
147 | |||
148 | /*NOTE: no need to lock here. The only times EFFECT_USED is | ||
149 | modified is when effects are uploaded or when an effect is | ||
150 | erased. But a process cannot close its dev/input/eventX fd | ||
151 | and perform ioctls on the same fd all at the same time */ | ||
152 | /*FIXME: multiple threads, anyone? */ | ||
153 | for (i = 0; i < dev->ff_effects_max; ++i) | ||
154 | if (current->pid == pid->effects[i].owner | ||
155 | && test_bit(FF_PID_FLAGS_USED, &pid->effects[i].flags)) | ||
156 | if (hid_pid_erase(dev, i)) | ||
157 | dev_warn(&hid->dev->dev, "erase effect %d failed", i); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int hid_pid_upload_effect(struct input_dev *dev, | ||
163 | struct ff_effect *effect) | ||
164 | { | ||
165 | struct hid_ff_pid *pid_private = (struct hid_ff_pid *)(dev->private); | ||
166 | int ret; | ||
167 | int is_update; | ||
168 | unsigned long flags; | ||
169 | |||
170 | dev_dbg(&pid_private->hid->dev->dev, "upload effect called: effect_type=%x\n", effect->type); | ||
171 | /* Check this effect type is supported by this device */ | ||
172 | if (!test_bit(effect->type, dev->ffbit)) { | ||
173 | dev_dbg(&pid_private->hid->dev->dev, | ||
174 | "invalid kind of effect requested.\n"); | ||
175 | return -EINVAL; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * If we want to create a new effect, get a free id | ||
180 | */ | ||
181 | if (effect->id == -1) { | ||
182 | int id = 0; | ||
183 | |||
184 | // Spinlock so we don`t get a race condition when choosing IDs | ||
185 | spin_lock_irqsave(&pid_private->lock, flags); | ||
186 | |||
187 | while (id < FF_EFFECTS_MAX) | ||
188 | if (!test_and_set_bit(FF_PID_FLAGS_USED, &pid_private->effects[id++].flags)) | ||
189 | break; | ||
190 | |||
191 | if (id == FF_EFFECTS_MAX) { | ||
192 | spin_unlock_irqrestore(&pid_private->lock, flags); | ||
193 | // TEMP - We need to get ff_effects_max correctly first: || id >= dev->ff_effects_max) { | ||
194 | dev_dbg(&pid_private->hid->dev->dev, "Not enough device memory\n"); | ||
195 | return -ENOMEM; | ||
196 | } | ||
197 | |||
198 | effect->id = id; | ||
199 | dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d.\n", id); | ||
200 | pid_private->effects[id].owner = current->pid; | ||
201 | pid_private->effects[id].flags = (1 << FF_PID_FLAGS_USED); | ||
202 | spin_unlock_irqrestore(&pid_private->lock, flags); | ||
203 | |||
204 | is_update = FF_PID_FALSE; | ||
205 | } else { | ||
206 | /* We want to update an effect */ | ||
207 | if (!CHECK_OWNERSHIP(effect->id, pid_private)) | ||
208 | return -EACCES; | ||
209 | |||
210 | /* Parameter type cannot be updated */ | ||
211 | if (effect->type != pid_private->effects[effect->id].effect.type) | ||
212 | return -EINVAL; | ||
213 | |||
214 | /* Check the effect is not already being updated */ | ||
215 | if (test_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags)) | ||
216 | return -EAGAIN; | ||
217 | |||
218 | is_update = FF_PID_TRUE; | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Upload the effect | ||
223 | */ | ||
224 | switch (effect->type) { | ||
225 | case FF_PERIODIC: | ||
226 | ret = pid_upload_periodic(pid_private, effect, is_update); | ||
227 | break; | ||
228 | |||
229 | case FF_CONSTANT: | ||
230 | ret = pid_upload_constant(pid_private, effect, is_update); | ||
231 | break; | ||
232 | |||
233 | case FF_SPRING: | ||
234 | case FF_FRICTION: | ||
235 | case FF_DAMPER: | ||
236 | case FF_INERTIA: | ||
237 | ret = pid_upload_condition(pid_private, effect, is_update); | ||
238 | break; | ||
239 | |||
240 | case FF_RAMP: | ||
241 | ret = pid_upload_ramp(pid_private, effect, is_update); | ||
242 | break; | ||
243 | |||
244 | default: | ||
245 | dev_dbg(&pid_private->hid->dev->dev, | ||
246 | "invalid type of effect requested - %x.\n", | ||
247 | effect->type); | ||
248 | return -EINVAL; | ||
249 | } | ||
250 | /* If a packet was sent, forbid new updates until we are notified | ||
251 | * that the packet was updated | ||
252 | */ | ||
253 | if (ret == 0) | ||
254 | set_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags); | ||
255 | pid_private->effects[effect->id].effect = *effect; | ||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | int hid_pid_init(struct hid_device *hid) | ||
260 | { | ||
261 | struct hid_ff_pid *private; | ||
262 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
263 | struct input_dev *input_dev = hidinput->input; | ||
264 | |||
265 | private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); | ||
266 | if (!private) | ||
267 | return -ENOMEM; | ||
268 | |||
269 | private->hid = hid; | ||
270 | |||
271 | hid->ff_exit = hid_pid_exit; | ||
272 | hid->ff_event = hid_pid_event; | ||
273 | |||
274 | /* Open output URB */ | ||
275 | if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) { | ||
276 | kfree(private); | ||
277 | return -1; | ||
278 | } | ||
279 | |||
280 | usb_fill_control_urb(private->urbffout, hid->dev, 0, | ||
281 | (void *)&private->ffcr, private->ctrl_buffer, 8, | ||
282 | hid_pid_ctrl_out, hid); | ||
283 | |||
284 | input_dev->upload_effect = hid_pid_upload_effect; | ||
285 | input_dev->flush = hid_pid_flush; | ||
286 | input_dev->ff_effects_max = 8; // A random default | ||
287 | set_bit(EV_FF, input_dev->evbit); | ||
288 | set_bit(EV_FF_STATUS, input_dev->evbit); | ||
289 | |||
290 | spin_lock_init(&private->lock); | ||
291 | |||
292 | printk(KERN_INFO "Force feedback driver for PID devices by Rodrigo Damazio <rdamazio@lsi.usp.br>.\n"); | ||
293 | |||
294 | return 0; | ||
295 | } | ||
diff --git a/drivers/usb/input/pid.h b/drivers/usb/input/pid.h deleted file mode 100644 index a2cb9627ed0e..000000000000 --- a/drivers/usb/input/pid.h +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | /* | ||
2 | * PID Force feedback support for hid devices. | ||
3 | * | ||
4 | * Copyright (c) 2002 Rodrigo Damazio. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | * Should you need to contact me, the author, you can do so by | ||
23 | * e-mail - mail your message to <rdamazio@lsi.usp.br> | ||
24 | */ | ||
25 | |||
26 | #define FF_EFFECTS_MAX 64 | ||
27 | |||
28 | #define FF_PID_FLAGS_USED 1 /* If the effect exists */ | ||
29 | #define FF_PID_FLAGS_UPDATING 2 /* If the effect is being updated */ | ||
30 | #define FF_PID_FLAGS_PLAYING 3 /* If the effect is currently being played */ | ||
31 | |||
32 | #define FF_PID_FALSE 0 | ||
33 | #define FF_PID_TRUE 1 | ||
34 | |||
35 | struct hid_pid_effect { | ||
36 | unsigned long flags; | ||
37 | pid_t owner; | ||
38 | unsigned int device_id; /* The device-assigned ID */ | ||
39 | struct ff_effect effect; | ||
40 | }; | ||
41 | |||
42 | struct hid_ff_pid { | ||
43 | struct hid_device *hid; | ||
44 | unsigned long gain; | ||
45 | |||
46 | struct urb *urbffout; | ||
47 | struct usb_ctrlrequest ffcr; | ||
48 | spinlock_t lock; | ||
49 | |||
50 | unsigned char ctrl_buffer[8]; | ||
51 | |||
52 | struct hid_pid_effect effects[FF_EFFECTS_MAX]; | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | * Constants from the PID usage table (still far from complete) | ||
57 | */ | ||
58 | |||
59 | #define FF_PID_USAGE_BLOCK_LOAD 0x89UL | ||
60 | #define FF_PID_USAGE_BLOCK_FREE 0x90UL | ||
61 | #define FF_PID_USAGE_NEW_EFFECT 0xABUL | ||
62 | #define FF_PID_USAGE_POOL_REPORT 0x7FUL | ||