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/input | |
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/input')
39 files changed, 2716 insertions, 789 deletions
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/input/fixp-arith.h b/drivers/input/fixp-arith.h new file mode 100644 index 000000000000..ed3d2da0c485 --- /dev/null +++ b/drivers/input/fixp-arith.h | |||
@@ -0,0 +1,87 @@ | |||
1 | #ifndef _FIXP_ARITH_H | ||
2 | #define _FIXP_ARITH_H | ||
3 | |||
4 | /* | ||
5 | * Simplistic fixed-point arithmetics. | ||
6 | * Hmm, I'm probably duplicating some code :( | ||
7 | * | ||
8 | * Copyright (c) 2002 Johann Deneux | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | * Should you need to contact me, the author, you can do so by | ||
27 | * e-mail - mail your message to <deneux@ifrance.com> | ||
28 | */ | ||
29 | |||
30 | #include <linux/types.h> | ||
31 | |||
32 | /* The type representing fixed-point values */ | ||
33 | typedef s16 fixp_t; | ||
34 | |||
35 | #define FRAC_N 8 | ||
36 | #define FRAC_MASK ((1<<FRAC_N)-1) | ||
37 | |||
38 | /* Not to be used directly. Use fixp_{cos,sin} */ | ||
39 | static const fixp_t cos_table[46] = { | ||
40 | 0x0100, 0x00FF, 0x00FF, 0x00FE, 0x00FD, 0x00FC, 0x00FA, 0x00F8, | ||
41 | 0x00F6, 0x00F3, 0x00F0, 0x00ED, 0x00E9, 0x00E6, 0x00E2, 0x00DD, | ||
42 | 0x00D9, 0x00D4, 0x00CF, 0x00C9, 0x00C4, 0x00BE, 0x00B8, 0x00B1, | ||
43 | 0x00AB, 0x00A4, 0x009D, 0x0096, 0x008F, 0x0087, 0x0080, 0x0078, | ||
44 | 0x0070, 0x0068, 0x005F, 0x0057, 0x004F, 0x0046, 0x003D, 0x0035, | ||
45 | 0x002C, 0x0023, 0x001A, 0x0011, 0x0008, 0x0000 | ||
46 | }; | ||
47 | |||
48 | |||
49 | /* a: 123 -> 123.0 */ | ||
50 | static inline fixp_t fixp_new(s16 a) | ||
51 | { | ||
52 | return a<<FRAC_N; | ||
53 | } | ||
54 | |||
55 | /* a: 0xFFFF -> -1.0 | ||
56 | 0x8000 -> 1.0 | ||
57 | 0x0000 -> 0.0 | ||
58 | */ | ||
59 | static inline fixp_t fixp_new16(s16 a) | ||
60 | { | ||
61 | return ((s32)a)>>(16-FRAC_N); | ||
62 | } | ||
63 | |||
64 | static inline fixp_t fixp_cos(unsigned int degrees) | ||
65 | { | ||
66 | int quadrant = (degrees / 90) & 3; | ||
67 | unsigned int i = degrees % 90; | ||
68 | |||
69 | if (quadrant == 1 || quadrant == 3) | ||
70 | i = 90 - i; | ||
71 | |||
72 | i >>= 1; | ||
73 | |||
74 | return (quadrant == 1 || quadrant == 2)? -cos_table[i] : cos_table[i]; | ||
75 | } | ||
76 | |||
77 | static inline fixp_t fixp_sin(unsigned int degrees) | ||
78 | { | ||
79 | return -fixp_cos(degrees + 90); | ||
80 | } | ||
81 | |||
82 | static inline fixp_t fixp_mult(fixp_t a, fixp_t b) | ||
83 | { | ||
84 | return ((s32)(a*b))>>FRAC_N; | ||
85 | } | ||
86 | |||
87 | #endif | ||
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) |