diff options
Diffstat (limited to 'drivers/input')
27 files changed, 3504 insertions, 1545 deletions
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 2d87357e2b2b..63512d906f02 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig | |||
@@ -114,28 +114,6 @@ config INPUT_JOYDEV | |||
114 | To compile this driver as a module, choose M here: the | 114 | To compile this driver as a module, choose M here: the |
115 | module will be called joydev. | 115 | module will be called joydev. |
116 | 116 | ||
117 | config INPUT_TSDEV | ||
118 | tristate "Touchscreen interface" | ||
119 | ---help--- | ||
120 | Say Y here if you have an application that only can understand the | ||
121 | Compaq touchscreen protocol for absolute pointer data. This is | ||
122 | useful namely for embedded configurations. | ||
123 | |||
124 | If unsure, say N. | ||
125 | |||
126 | To compile this driver as a module, choose M here: the | ||
127 | module will be called tsdev. | ||
128 | |||
129 | config INPUT_TSDEV_SCREEN_X | ||
130 | int "Horizontal screen resolution" | ||
131 | depends on INPUT_TSDEV | ||
132 | default "240" | ||
133 | |||
134 | config INPUT_TSDEV_SCREEN_Y | ||
135 | int "Vertical screen resolution" | ||
136 | depends on INPUT_TSDEV | ||
137 | default "320" | ||
138 | |||
139 | config INPUT_EVDEV | 117 | config INPUT_EVDEV |
140 | tristate "Event interface" | 118 | tristate "Event interface" |
141 | help | 119 | help |
diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 15eb752697b3..99af903bd3ce 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile | |||
@@ -13,7 +13,6 @@ obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o | |||
13 | obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o | 13 | obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o |
14 | obj-$(CONFIG_INPUT_JOYDEV) += joydev.o | 14 | obj-$(CONFIG_INPUT_JOYDEV) += joydev.o |
15 | obj-$(CONFIG_INPUT_EVDEV) += evdev.o | 15 | obj-$(CONFIG_INPUT_EVDEV) += evdev.o |
16 | obj-$(CONFIG_INPUT_TSDEV) += tsdev.o | ||
17 | obj-$(CONFIG_INPUT_EVBUG) += evbug.o | 16 | obj-$(CONFIG_INPUT_EVBUG) += evbug.o |
18 | 17 | ||
19 | obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/ | 18 | obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/ |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index f1c3d6cebd58..1d62c8b88e12 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -30,6 +30,8 @@ struct evdev { | |||
30 | wait_queue_head_t wait; | 30 | wait_queue_head_t wait; |
31 | struct evdev_client *grab; | 31 | struct evdev_client *grab; |
32 | struct list_head client_list; | 32 | struct list_head client_list; |
33 | spinlock_t client_lock; /* protects client_list */ | ||
34 | struct mutex mutex; | ||
33 | struct device dev; | 35 | struct device dev; |
34 | }; | 36 | }; |
35 | 37 | ||
@@ -37,39 +39,54 @@ struct evdev_client { | |||
37 | struct input_event buffer[EVDEV_BUFFER_SIZE]; | 39 | struct input_event buffer[EVDEV_BUFFER_SIZE]; |
38 | int head; | 40 | int head; |
39 | int tail; | 41 | int tail; |
42 | spinlock_t buffer_lock; /* protects access to buffer, head and tail */ | ||
40 | struct fasync_struct *fasync; | 43 | struct fasync_struct *fasync; |
41 | struct evdev *evdev; | 44 | struct evdev *evdev; |
42 | struct list_head node; | 45 | struct list_head node; |
43 | }; | 46 | }; |
44 | 47 | ||
45 | static struct evdev *evdev_table[EVDEV_MINORS]; | 48 | static struct evdev *evdev_table[EVDEV_MINORS]; |
49 | static DEFINE_MUTEX(evdev_table_mutex); | ||
46 | 50 | ||
47 | static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 51 | static void evdev_pass_event(struct evdev_client *client, |
52 | struct input_event *event) | ||
53 | { | ||
54 | /* | ||
55 | * Interrupts are disabled, just acquire the lock | ||
56 | */ | ||
57 | spin_lock(&client->buffer_lock); | ||
58 | client->buffer[client->head++] = *event; | ||
59 | client->head &= EVDEV_BUFFER_SIZE - 1; | ||
60 | spin_unlock(&client->buffer_lock); | ||
61 | |||
62 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * Pass incoming event to all connected clients. | ||
67 | */ | ||
68 | static void evdev_event(struct input_handle *handle, | ||
69 | unsigned int type, unsigned int code, int value) | ||
48 | { | 70 | { |
49 | struct evdev *evdev = handle->private; | 71 | struct evdev *evdev = handle->private; |
50 | struct evdev_client *client; | 72 | struct evdev_client *client; |
73 | struct input_event event; | ||
51 | 74 | ||
52 | if (evdev->grab) { | 75 | do_gettimeofday(&event.time); |
53 | client = evdev->grab; | 76 | event.type = type; |
77 | event.code = code; | ||
78 | event.value = value; | ||
54 | 79 | ||
55 | do_gettimeofday(&client->buffer[client->head].time); | 80 | rcu_read_lock(); |
56 | client->buffer[client->head].type = type; | ||
57 | client->buffer[client->head].code = code; | ||
58 | client->buffer[client->head].value = value; | ||
59 | client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
60 | 81 | ||
61 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | 82 | client = rcu_dereference(evdev->grab); |
62 | } else | 83 | if (client) |
63 | list_for_each_entry(client, &evdev->client_list, node) { | 84 | evdev_pass_event(client, &event); |
85 | else | ||
86 | list_for_each_entry_rcu(client, &evdev->client_list, node) | ||
87 | evdev_pass_event(client, &event); | ||
64 | 88 | ||
65 | do_gettimeofday(&client->buffer[client->head].time); | 89 | rcu_read_unlock(); |
66 | client->buffer[client->head].type = type; | ||
67 | client->buffer[client->head].code = code; | ||
68 | client->buffer[client->head].value = value; | ||
69 | client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
70 | |||
71 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
72 | } | ||
73 | 90 | ||
74 | wake_up_interruptible(&evdev->wait); | 91 | wake_up_interruptible(&evdev->wait); |
75 | } | 92 | } |
@@ -88,38 +105,140 @@ static int evdev_flush(struct file *file, fl_owner_t id) | |||
88 | { | 105 | { |
89 | struct evdev_client *client = file->private_data; | 106 | struct evdev_client *client = file->private_data; |
90 | struct evdev *evdev = client->evdev; | 107 | struct evdev *evdev = client->evdev; |
108 | int retval; | ||
109 | |||
110 | retval = mutex_lock_interruptible(&evdev->mutex); | ||
111 | if (retval) | ||
112 | return retval; | ||
91 | 113 | ||
92 | if (!evdev->exist) | 114 | if (!evdev->exist) |
93 | return -ENODEV; | 115 | retval = -ENODEV; |
116 | else | ||
117 | retval = input_flush_device(&evdev->handle, file); | ||
94 | 118 | ||
95 | return input_flush_device(&evdev->handle, file); | 119 | mutex_unlock(&evdev->mutex); |
120 | return retval; | ||
96 | } | 121 | } |
97 | 122 | ||
98 | static void evdev_free(struct device *dev) | 123 | static void evdev_free(struct device *dev) |
99 | { | 124 | { |
100 | struct evdev *evdev = container_of(dev, struct evdev, dev); | 125 | struct evdev *evdev = container_of(dev, struct evdev, dev); |
101 | 126 | ||
102 | evdev_table[evdev->minor] = NULL; | ||
103 | kfree(evdev); | 127 | kfree(evdev); |
104 | } | 128 | } |
105 | 129 | ||
130 | /* | ||
131 | * Grabs an event device (along with underlying input device). | ||
132 | * This function is called with evdev->mutex taken. | ||
133 | */ | ||
134 | static int evdev_grab(struct evdev *evdev, struct evdev_client *client) | ||
135 | { | ||
136 | int error; | ||
137 | |||
138 | if (evdev->grab) | ||
139 | return -EBUSY; | ||
140 | |||
141 | error = input_grab_device(&evdev->handle); | ||
142 | if (error) | ||
143 | return error; | ||
144 | |||
145 | rcu_assign_pointer(evdev->grab, client); | ||
146 | synchronize_rcu(); | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client) | ||
152 | { | ||
153 | if (evdev->grab != client) | ||
154 | return -EINVAL; | ||
155 | |||
156 | rcu_assign_pointer(evdev->grab, NULL); | ||
157 | synchronize_rcu(); | ||
158 | input_release_device(&evdev->handle); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static void evdev_attach_client(struct evdev *evdev, | ||
164 | struct evdev_client *client) | ||
165 | { | ||
166 | spin_lock(&evdev->client_lock); | ||
167 | list_add_tail_rcu(&client->node, &evdev->client_list); | ||
168 | spin_unlock(&evdev->client_lock); | ||
169 | synchronize_rcu(); | ||
170 | } | ||
171 | |||
172 | static void evdev_detach_client(struct evdev *evdev, | ||
173 | struct evdev_client *client) | ||
174 | { | ||
175 | spin_lock(&evdev->client_lock); | ||
176 | list_del_rcu(&client->node); | ||
177 | spin_unlock(&evdev->client_lock); | ||
178 | synchronize_rcu(); | ||
179 | } | ||
180 | |||
181 | static int evdev_open_device(struct evdev *evdev) | ||
182 | { | ||
183 | int retval; | ||
184 | |||
185 | retval = mutex_lock_interruptible(&evdev->mutex); | ||
186 | if (retval) | ||
187 | return retval; | ||
188 | |||
189 | if (!evdev->exist) | ||
190 | retval = -ENODEV; | ||
191 | else if (!evdev->open++) { | ||
192 | retval = input_open_device(&evdev->handle); | ||
193 | if (retval) | ||
194 | evdev->open--; | ||
195 | } | ||
196 | |||
197 | mutex_unlock(&evdev->mutex); | ||
198 | return retval; | ||
199 | } | ||
200 | |||
201 | static void evdev_close_device(struct evdev *evdev) | ||
202 | { | ||
203 | mutex_lock(&evdev->mutex); | ||
204 | |||
205 | if (evdev->exist && !--evdev->open) | ||
206 | input_close_device(&evdev->handle); | ||
207 | |||
208 | mutex_unlock(&evdev->mutex); | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * Wake up users waiting for IO so they can disconnect from | ||
213 | * dead device. | ||
214 | */ | ||
215 | static void evdev_hangup(struct evdev *evdev) | ||
216 | { | ||
217 | struct evdev_client *client; | ||
218 | |||
219 | spin_lock(&evdev->client_lock); | ||
220 | list_for_each_entry(client, &evdev->client_list, node) | ||
221 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
222 | spin_unlock(&evdev->client_lock); | ||
223 | |||
224 | wake_up_interruptible(&evdev->wait); | ||
225 | } | ||
226 | |||
106 | static int evdev_release(struct inode *inode, struct file *file) | 227 | static int evdev_release(struct inode *inode, struct file *file) |
107 | { | 228 | { |
108 | struct evdev_client *client = file->private_data; | 229 | struct evdev_client *client = file->private_data; |
109 | struct evdev *evdev = client->evdev; | 230 | struct evdev *evdev = client->evdev; |
110 | 231 | ||
111 | if (evdev->grab == client) { | 232 | mutex_lock(&evdev->mutex); |
112 | input_release_device(&evdev->handle); | 233 | if (evdev->grab == client) |
113 | evdev->grab = NULL; | 234 | evdev_ungrab(evdev, client); |
114 | } | 235 | mutex_unlock(&evdev->mutex); |
115 | 236 | ||
116 | evdev_fasync(-1, file, 0); | 237 | evdev_fasync(-1, file, 0); |
117 | list_del(&client->node); | 238 | evdev_detach_client(evdev, client); |
118 | kfree(client); | 239 | kfree(client); |
119 | 240 | ||
120 | if (!--evdev->open && evdev->exist) | 241 | evdev_close_device(evdev); |
121 | input_close_device(&evdev->handle); | ||
122 | |||
123 | put_device(&evdev->dev); | 242 | put_device(&evdev->dev); |
124 | 243 | ||
125 | return 0; | 244 | return 0; |
@@ -127,41 +246,44 @@ static int evdev_release(struct inode *inode, struct file *file) | |||
127 | 246 | ||
128 | static int evdev_open(struct inode *inode, struct file *file) | 247 | static int evdev_open(struct inode *inode, struct file *file) |
129 | { | 248 | { |
130 | struct evdev_client *client; | ||
131 | struct evdev *evdev; | 249 | struct evdev *evdev; |
250 | struct evdev_client *client; | ||
132 | int i = iminor(inode) - EVDEV_MINOR_BASE; | 251 | int i = iminor(inode) - EVDEV_MINOR_BASE; |
133 | int error; | 252 | int error; |
134 | 253 | ||
135 | if (i >= EVDEV_MINORS) | 254 | if (i >= EVDEV_MINORS) |
136 | return -ENODEV; | 255 | return -ENODEV; |
137 | 256 | ||
257 | error = mutex_lock_interruptible(&evdev_table_mutex); | ||
258 | if (error) | ||
259 | return error; | ||
138 | evdev = evdev_table[i]; | 260 | evdev = evdev_table[i]; |
261 | if (evdev) | ||
262 | get_device(&evdev->dev); | ||
263 | mutex_unlock(&evdev_table_mutex); | ||
139 | 264 | ||
140 | if (!evdev || !evdev->exist) | 265 | if (!evdev) |
141 | return -ENODEV; | 266 | return -ENODEV; |
142 | 267 | ||
143 | get_device(&evdev->dev); | ||
144 | |||
145 | client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); | 268 | client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); |
146 | if (!client) { | 269 | if (!client) { |
147 | error = -ENOMEM; | 270 | error = -ENOMEM; |
148 | goto err_put_evdev; | 271 | goto err_put_evdev; |
149 | } | 272 | } |
150 | 273 | ||
274 | spin_lock_init(&client->buffer_lock); | ||
151 | client->evdev = evdev; | 275 | client->evdev = evdev; |
152 | list_add_tail(&client->node, &evdev->client_list); | 276 | evdev_attach_client(evdev, client); |
153 | 277 | ||
154 | if (!evdev->open++ && evdev->exist) { | 278 | error = evdev_open_device(evdev); |
155 | error = input_open_device(&evdev->handle); | 279 | if (error) |
156 | if (error) | 280 | goto err_free_client; |
157 | goto err_free_client; | ||
158 | } | ||
159 | 281 | ||
160 | file->private_data = client; | 282 | file->private_data = client; |
161 | return 0; | 283 | return 0; |
162 | 284 | ||
163 | err_free_client: | 285 | err_free_client: |
164 | list_del(&client->node); | 286 | evdev_detach_client(evdev, client); |
165 | kfree(client); | 287 | kfree(client); |
166 | err_put_evdev: | 288 | err_put_evdev: |
167 | put_device(&evdev->dev); | 289 | put_device(&evdev->dev); |
@@ -197,12 +319,14 @@ static inline size_t evdev_event_size(void) | |||
197 | sizeof(struct input_event_compat) : sizeof(struct input_event); | 319 | sizeof(struct input_event_compat) : sizeof(struct input_event); |
198 | } | 320 | } |
199 | 321 | ||
200 | static int evdev_event_from_user(const char __user *buffer, struct input_event *event) | 322 | static int evdev_event_from_user(const char __user *buffer, |
323 | struct input_event *event) | ||
201 | { | 324 | { |
202 | if (COMPAT_TEST) { | 325 | if (COMPAT_TEST) { |
203 | struct input_event_compat compat_event; | 326 | struct input_event_compat compat_event; |
204 | 327 | ||
205 | if (copy_from_user(&compat_event, buffer, sizeof(struct input_event_compat))) | 328 | if (copy_from_user(&compat_event, buffer, |
329 | sizeof(struct input_event_compat))) | ||
206 | return -EFAULT; | 330 | return -EFAULT; |
207 | 331 | ||
208 | event->time.tv_sec = compat_event.time.tv_sec; | 332 | event->time.tv_sec = compat_event.time.tv_sec; |
@@ -219,7 +343,8 @@ static int evdev_event_from_user(const char __user *buffer, struct input_event * | |||
219 | return 0; | 343 | return 0; |
220 | } | 344 | } |
221 | 345 | ||
222 | static int evdev_event_to_user(char __user *buffer, const struct input_event *event) | 346 | static int evdev_event_to_user(char __user *buffer, |
347 | const struct input_event *event) | ||
223 | { | 348 | { |
224 | if (COMPAT_TEST) { | 349 | if (COMPAT_TEST) { |
225 | struct input_event_compat compat_event; | 350 | struct input_event_compat compat_event; |
@@ -230,7 +355,8 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev | |||
230 | compat_event.code = event->code; | 355 | compat_event.code = event->code; |
231 | compat_event.value = event->value; | 356 | compat_event.value = event->value; |
232 | 357 | ||
233 | if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat))) | 358 | if (copy_to_user(buffer, &compat_event, |
359 | sizeof(struct input_event_compat))) | ||
234 | return -EFAULT; | 360 | return -EFAULT; |
235 | 361 | ||
236 | } else { | 362 | } else { |
@@ -248,7 +374,8 @@ static inline size_t evdev_event_size(void) | |||
248 | return sizeof(struct input_event); | 374 | return sizeof(struct input_event); |
249 | } | 375 | } |
250 | 376 | ||
251 | static int evdev_event_from_user(const char __user *buffer, struct input_event *event) | 377 | static int evdev_event_from_user(const char __user *buffer, |
378 | struct input_event *event) | ||
252 | { | 379 | { |
253 | if (copy_from_user(event, buffer, sizeof(struct input_event))) | 380 | if (copy_from_user(event, buffer, sizeof(struct input_event))) |
254 | return -EFAULT; | 381 | return -EFAULT; |
@@ -256,7 +383,8 @@ static int evdev_event_from_user(const char __user *buffer, struct input_event * | |||
256 | return 0; | 383 | return 0; |
257 | } | 384 | } |
258 | 385 | ||
259 | static int evdev_event_to_user(char __user *buffer, const struct input_event *event) | 386 | static int evdev_event_to_user(char __user *buffer, |
387 | const struct input_event *event) | ||
260 | { | 388 | { |
261 | if (copy_to_user(buffer, event, sizeof(struct input_event))) | 389 | if (copy_to_user(buffer, event, sizeof(struct input_event))) |
262 | return -EFAULT; | 390 | return -EFAULT; |
@@ -266,37 +394,71 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev | |||
266 | 394 | ||
267 | #endif /* CONFIG_COMPAT */ | 395 | #endif /* CONFIG_COMPAT */ |
268 | 396 | ||
269 | static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 397 | static ssize_t evdev_write(struct file *file, const char __user *buffer, |
398 | size_t count, loff_t *ppos) | ||
270 | { | 399 | { |
271 | struct evdev_client *client = file->private_data; | 400 | struct evdev_client *client = file->private_data; |
272 | struct evdev *evdev = client->evdev; | 401 | struct evdev *evdev = client->evdev; |
273 | struct input_event event; | 402 | struct input_event event; |
274 | int retval = 0; | 403 | int retval; |
275 | 404 | ||
276 | if (!evdev->exist) | 405 | retval = mutex_lock_interruptible(&evdev->mutex); |
277 | return -ENODEV; | 406 | if (retval) |
407 | return retval; | ||
408 | |||
409 | if (!evdev->exist) { | ||
410 | retval = -ENODEV; | ||
411 | goto out; | ||
412 | } | ||
278 | 413 | ||
279 | while (retval < count) { | 414 | while (retval < count) { |
280 | 415 | ||
281 | if (evdev_event_from_user(buffer + retval, &event)) | 416 | if (evdev_event_from_user(buffer + retval, &event)) { |
282 | return -EFAULT; | 417 | retval = -EFAULT; |
283 | input_inject_event(&evdev->handle, event.type, event.code, event.value); | 418 | goto out; |
419 | } | ||
420 | |||
421 | input_inject_event(&evdev->handle, | ||
422 | event.type, event.code, event.value); | ||
284 | retval += evdev_event_size(); | 423 | retval += evdev_event_size(); |
285 | } | 424 | } |
286 | 425 | ||
426 | out: | ||
427 | mutex_unlock(&evdev->mutex); | ||
287 | return retval; | 428 | return retval; |
288 | } | 429 | } |
289 | 430 | ||
290 | static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 431 | static int evdev_fetch_next_event(struct evdev_client *client, |
432 | struct input_event *event) | ||
433 | { | ||
434 | int have_event; | ||
435 | |||
436 | spin_lock_irq(&client->buffer_lock); | ||
437 | |||
438 | have_event = client->head != client->tail; | ||
439 | if (have_event) { | ||
440 | *event = client->buffer[client->tail++]; | ||
441 | client->tail &= EVDEV_BUFFER_SIZE - 1; | ||
442 | } | ||
443 | |||
444 | spin_unlock_irq(&client->buffer_lock); | ||
445 | |||
446 | return have_event; | ||
447 | } | ||
448 | |||
449 | static ssize_t evdev_read(struct file *file, char __user *buffer, | ||
450 | size_t count, loff_t *ppos) | ||
291 | { | 451 | { |
292 | struct evdev_client *client = file->private_data; | 452 | struct evdev_client *client = file->private_data; |
293 | struct evdev *evdev = client->evdev; | 453 | struct evdev *evdev = client->evdev; |
454 | struct input_event event; | ||
294 | int retval; | 455 | int retval; |
295 | 456 | ||
296 | if (count < evdev_event_size()) | 457 | if (count < evdev_event_size()) |
297 | return -EINVAL; | 458 | return -EINVAL; |
298 | 459 | ||
299 | if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK)) | 460 | if (client->head == client->tail && evdev->exist && |
461 | (file->f_flags & O_NONBLOCK)) | ||
300 | return -EAGAIN; | 462 | return -EAGAIN; |
301 | 463 | ||
302 | retval = wait_event_interruptible(evdev->wait, | 464 | retval = wait_event_interruptible(evdev->wait, |
@@ -307,14 +469,12 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, | |||
307 | if (!evdev->exist) | 469 | if (!evdev->exist) |
308 | return -ENODEV; | 470 | return -ENODEV; |
309 | 471 | ||
310 | while (client->head != client->tail && retval + evdev_event_size() <= count) { | 472 | while (retval + evdev_event_size() <= count && |
311 | 473 | evdev_fetch_next_event(client, &event)) { | |
312 | struct input_event *event = (struct input_event *) client->buffer + client->tail; | ||
313 | 474 | ||
314 | if (evdev_event_to_user(buffer + retval, event)) | 475 | if (evdev_event_to_user(buffer + retval, &event)) |
315 | return -EFAULT; | 476 | return -EFAULT; |
316 | 477 | ||
317 | client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
318 | retval += evdev_event_size(); | 478 | retval += evdev_event_size(); |
319 | } | 479 | } |
320 | 480 | ||
@@ -409,8 +569,8 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) | |||
409 | return copy_to_user(p, str, len) ? -EFAULT : len; | 569 | return copy_to_user(p, str, len) ? -EFAULT : len; |
410 | } | 570 | } |
411 | 571 | ||
412 | static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | 572 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, |
413 | void __user *p, int compat_mode) | 573 | void __user *p, int compat_mode) |
414 | { | 574 | { |
415 | struct evdev_client *client = file->private_data; | 575 | struct evdev_client *client = file->private_data; |
416 | struct evdev *evdev = client->evdev; | 576 | struct evdev *evdev = client->evdev; |
@@ -421,215 +581,289 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | |||
421 | int i, t, u, v; | 581 | int i, t, u, v; |
422 | int error; | 582 | int error; |
423 | 583 | ||
424 | if (!evdev->exist) | ||
425 | return -ENODEV; | ||
426 | |||
427 | switch (cmd) { | 584 | switch (cmd) { |
428 | 585 | ||
429 | case EVIOCGVERSION: | 586 | case EVIOCGVERSION: |
430 | return put_user(EV_VERSION, ip); | 587 | return put_user(EV_VERSION, ip); |
431 | 588 | ||
432 | case EVIOCGID: | 589 | case EVIOCGID: |
433 | if (copy_to_user(p, &dev->id, sizeof(struct input_id))) | 590 | if (copy_to_user(p, &dev->id, sizeof(struct input_id))) |
434 | return -EFAULT; | 591 | return -EFAULT; |
435 | return 0; | 592 | return 0; |
436 | 593 | ||
437 | case EVIOCGREP: | 594 | case EVIOCGREP: |
438 | if (!test_bit(EV_REP, dev->evbit)) | 595 | if (!test_bit(EV_REP, dev->evbit)) |
439 | return -ENOSYS; | 596 | return -ENOSYS; |
440 | if (put_user(dev->rep[REP_DELAY], ip)) | 597 | if (put_user(dev->rep[REP_DELAY], ip)) |
441 | return -EFAULT; | 598 | return -EFAULT; |
442 | if (put_user(dev->rep[REP_PERIOD], ip + 1)) | 599 | if (put_user(dev->rep[REP_PERIOD], ip + 1)) |
443 | return -EFAULT; | 600 | return -EFAULT; |
444 | return 0; | 601 | return 0; |
445 | 602 | ||
446 | case EVIOCSREP: | 603 | case EVIOCSREP: |
447 | if (!test_bit(EV_REP, dev->evbit)) | 604 | if (!test_bit(EV_REP, dev->evbit)) |
448 | return -ENOSYS; | 605 | return -ENOSYS; |
449 | if (get_user(u, ip)) | 606 | if (get_user(u, ip)) |
450 | return -EFAULT; | 607 | return -EFAULT; |
451 | if (get_user(v, ip + 1)) | 608 | if (get_user(v, ip + 1)) |
452 | return -EFAULT; | 609 | return -EFAULT; |
453 | 610 | ||
454 | input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); | 611 | input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); |
455 | input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); | 612 | input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); |
456 | 613 | ||
457 | return 0; | 614 | return 0; |
458 | 615 | ||
459 | case EVIOCGKEYCODE: | 616 | case EVIOCGKEYCODE: |
460 | if (get_user(t, ip)) | 617 | if (get_user(t, ip)) |
461 | return -EFAULT; | 618 | return -EFAULT; |
462 | 619 | ||
463 | error = dev->getkeycode(dev, t, &v); | 620 | error = dev->getkeycode(dev, t, &v); |
464 | if (error) | 621 | if (error) |
465 | return error; | 622 | return error; |
466 | 623 | ||
467 | if (put_user(v, ip + 1)) | 624 | if (put_user(v, ip + 1)) |
468 | return -EFAULT; | 625 | return -EFAULT; |
469 | 626 | ||
470 | return 0; | 627 | return 0; |
471 | 628 | ||
472 | case EVIOCSKEYCODE: | 629 | case EVIOCSKEYCODE: |
473 | if (get_user(t, ip) || get_user(v, ip + 1)) | 630 | if (get_user(t, ip) || get_user(v, ip + 1)) |
474 | return -EFAULT; | 631 | return -EFAULT; |
475 | 632 | ||
476 | return dev->setkeycode(dev, t, v); | 633 | return dev->setkeycode(dev, t, v); |
477 | 634 | ||
478 | case EVIOCSFF: | 635 | case EVIOCSFF: |
479 | if (copy_from_user(&effect, p, sizeof(effect))) | 636 | if (copy_from_user(&effect, p, sizeof(effect))) |
480 | return -EFAULT; | 637 | return -EFAULT; |
481 | 638 | ||
482 | error = input_ff_upload(dev, &effect, file); | 639 | error = input_ff_upload(dev, &effect, file); |
483 | 640 | ||
484 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) | 641 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) |
485 | return -EFAULT; | 642 | return -EFAULT; |
486 | 643 | ||
487 | return error; | 644 | return error; |
488 | 645 | ||
489 | case EVIOCRMFF: | 646 | case EVIOCRMFF: |
490 | return input_ff_erase(dev, (int)(unsigned long) p, file); | 647 | return input_ff_erase(dev, (int)(unsigned long) p, file); |
491 | 648 | ||
492 | case EVIOCGEFFECTS: | 649 | case EVIOCGEFFECTS: |
493 | i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0; | 650 | i = test_bit(EV_FF, dev->evbit) ? |
494 | if (put_user(i, ip)) | 651 | dev->ff->max_effects : 0; |
495 | return -EFAULT; | 652 | if (put_user(i, ip)) |
496 | return 0; | 653 | return -EFAULT; |
497 | 654 | return 0; | |
498 | case EVIOCGRAB: | 655 | |
499 | if (p) { | 656 | case EVIOCGRAB: |
500 | if (evdev->grab) | 657 | if (p) |
501 | return -EBUSY; | 658 | return evdev_grab(evdev, client); |
502 | if (input_grab_device(&evdev->handle)) | 659 | else |
503 | return -EBUSY; | 660 | return evdev_ungrab(evdev, client); |
504 | evdev->grab = client; | ||
505 | return 0; | ||
506 | } else { | ||
507 | if (evdev->grab != client) | ||
508 | return -EINVAL; | ||
509 | input_release_device(&evdev->handle); | ||
510 | evdev->grab = NULL; | ||
511 | return 0; | ||
512 | } | ||
513 | 661 | ||
514 | default: | 662 | default: |
515 | 663 | ||
516 | if (_IOC_TYPE(cmd) != 'E') | 664 | if (_IOC_TYPE(cmd) != 'E') |
517 | return -EINVAL; | 665 | return -EINVAL; |
518 | 666 | ||
519 | if (_IOC_DIR(cmd) == _IOC_READ) { | 667 | if (_IOC_DIR(cmd) == _IOC_READ) { |
520 | 668 | ||
521 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | 669 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) { |
522 | 670 | ||
523 | unsigned long *bits; | 671 | unsigned long *bits; |
524 | int len; | 672 | int len; |
525 | 673 | ||
526 | switch (_IOC_NR(cmd) & EV_MAX) { | 674 | switch (_IOC_NR(cmd) & EV_MAX) { |
527 | case 0: bits = dev->evbit; len = EV_MAX; break; | ||
528 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | ||
529 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; | ||
530 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | ||
531 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | ||
532 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | ||
533 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | ||
534 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
535 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | ||
536 | default: return -EINVAL; | ||
537 | } | ||
538 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | ||
539 | } | ||
540 | 675 | ||
541 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | 676 | case 0: bits = dev->evbit; len = EV_MAX; break; |
542 | return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), | 677 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; |
543 | p, compat_mode); | 678 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; |
679 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | ||
680 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | ||
681 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | ||
682 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | ||
683 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
684 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | ||
685 | default: return -EINVAL; | ||
686 | } | ||
687 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | ||
688 | } | ||
544 | 689 | ||
545 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) | 690 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) |
546 | return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), | 691 | return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), |
547 | p, compat_mode); | 692 | p, compat_mode); |
548 | 693 | ||
549 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) | 694 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) |
550 | return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), | 695 | return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), |
551 | p, compat_mode); | 696 | p, compat_mode); |
552 | 697 | ||
553 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) | 698 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) |
554 | return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), | 699 | return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), |
555 | p, compat_mode); | 700 | p, compat_mode); |
556 | 701 | ||
557 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) | 702 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) |
558 | return str_to_user(dev->name, _IOC_SIZE(cmd), p); | 703 | return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), |
704 | p, compat_mode); | ||
559 | 705 | ||
560 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) | 706 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) |
561 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); | 707 | return str_to_user(dev->name, _IOC_SIZE(cmd), p); |
562 | 708 | ||
563 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) | 709 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) |
564 | return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); | 710 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); |
565 | 711 | ||
566 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | 712 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) |
713 | return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); | ||
567 | 714 | ||
568 | t = _IOC_NR(cmd) & ABS_MAX; | 715 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { |
569 | 716 | ||
570 | abs.value = dev->abs[t]; | 717 | t = _IOC_NR(cmd) & ABS_MAX; |
571 | abs.minimum = dev->absmin[t]; | ||
572 | abs.maximum = dev->absmax[t]; | ||
573 | abs.fuzz = dev->absfuzz[t]; | ||
574 | abs.flat = dev->absflat[t]; | ||
575 | 718 | ||
576 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | 719 | abs.value = dev->abs[t]; |
577 | return -EFAULT; | 720 | abs.minimum = dev->absmin[t]; |
721 | abs.maximum = dev->absmax[t]; | ||
722 | abs.fuzz = dev->absfuzz[t]; | ||
723 | abs.flat = dev->absflat[t]; | ||
578 | 724 | ||
579 | return 0; | 725 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) |
580 | } | 726 | return -EFAULT; |
581 | 727 | ||
728 | return 0; | ||
582 | } | 729 | } |
583 | 730 | ||
584 | if (_IOC_DIR(cmd) == _IOC_WRITE) { | 731 | } |
732 | |||
733 | if (_IOC_DIR(cmd) == _IOC_WRITE) { | ||
585 | 734 | ||
586 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | 735 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
587 | 736 | ||
588 | t = _IOC_NR(cmd) & ABS_MAX; | 737 | t = _IOC_NR(cmd) & ABS_MAX; |
589 | 738 | ||
590 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | 739 | if (copy_from_user(&abs, p, |
591 | return -EFAULT; | 740 | sizeof(struct input_absinfo))) |
741 | return -EFAULT; | ||
592 | 742 | ||
593 | dev->abs[t] = abs.value; | 743 | /* |
594 | dev->absmin[t] = abs.minimum; | 744 | * Take event lock to ensure that we are not |
595 | dev->absmax[t] = abs.maximum; | 745 | * changing device parameters in the middle |
596 | dev->absfuzz[t] = abs.fuzz; | 746 | * of event. |
597 | dev->absflat[t] = abs.flat; | 747 | */ |
748 | spin_lock_irq(&dev->event_lock); | ||
598 | 749 | ||
599 | return 0; | 750 | dev->abs[t] = abs.value; |
600 | } | 751 | dev->absmin[t] = abs.minimum; |
752 | dev->absmax[t] = abs.maximum; | ||
753 | dev->absfuzz[t] = abs.fuzz; | ||
754 | dev->absflat[t] = abs.flat; | ||
755 | |||
756 | spin_unlock_irq(&dev->event_lock); | ||
757 | |||
758 | return 0; | ||
601 | } | 759 | } |
760 | } | ||
602 | } | 761 | } |
603 | return -EINVAL; | 762 | return -EINVAL; |
604 | } | 763 | } |
605 | 764 | ||
765 | static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | ||
766 | void __user *p, int compat_mode) | ||
767 | { | ||
768 | struct evdev_client *client = file->private_data; | ||
769 | struct evdev *evdev = client->evdev; | ||
770 | int retval; | ||
771 | |||
772 | retval = mutex_lock_interruptible(&evdev->mutex); | ||
773 | if (retval) | ||
774 | return retval; | ||
775 | |||
776 | if (!evdev->exist) { | ||
777 | retval = -ENODEV; | ||
778 | goto out; | ||
779 | } | ||
780 | |||
781 | retval = evdev_do_ioctl(file, cmd, p, compat_mode); | ||
782 | |||
783 | out: | ||
784 | mutex_unlock(&evdev->mutex); | ||
785 | return retval; | ||
786 | } | ||
787 | |||
606 | static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 788 | static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
607 | { | 789 | { |
608 | return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0); | 790 | return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0); |
609 | } | 791 | } |
610 | 792 | ||
611 | #ifdef CONFIG_COMPAT | 793 | #ifdef CONFIG_COMPAT |
612 | static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | 794 | static long evdev_ioctl_compat(struct file *file, |
795 | unsigned int cmd, unsigned long arg) | ||
613 | { | 796 | { |
614 | return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); | 797 | return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); |
615 | } | 798 | } |
616 | #endif | 799 | #endif |
617 | 800 | ||
618 | static const struct file_operations evdev_fops = { | 801 | static const struct file_operations evdev_fops = { |
619 | .owner = THIS_MODULE, | 802 | .owner = THIS_MODULE, |
620 | .read = evdev_read, | 803 | .read = evdev_read, |
621 | .write = evdev_write, | 804 | .write = evdev_write, |
622 | .poll = evdev_poll, | 805 | .poll = evdev_poll, |
623 | .open = evdev_open, | 806 | .open = evdev_open, |
624 | .release = evdev_release, | 807 | .release = evdev_release, |
625 | .unlocked_ioctl = evdev_ioctl, | 808 | .unlocked_ioctl = evdev_ioctl, |
626 | #ifdef CONFIG_COMPAT | 809 | #ifdef CONFIG_COMPAT |
627 | .compat_ioctl = evdev_ioctl_compat, | 810 | .compat_ioctl = evdev_ioctl_compat, |
628 | #endif | 811 | #endif |
629 | .fasync = evdev_fasync, | 812 | .fasync = evdev_fasync, |
630 | .flush = evdev_flush | 813 | .flush = evdev_flush |
631 | }; | 814 | }; |
632 | 815 | ||
816 | static int evdev_install_chrdev(struct evdev *evdev) | ||
817 | { | ||
818 | /* | ||
819 | * No need to do any locking here as calls to connect and | ||
820 | * disconnect are serialized by the input core | ||
821 | */ | ||
822 | evdev_table[evdev->minor] = evdev; | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static void evdev_remove_chrdev(struct evdev *evdev) | ||
827 | { | ||
828 | /* | ||
829 | * Lock evdev table to prevent race with evdev_open() | ||
830 | */ | ||
831 | mutex_lock(&evdev_table_mutex); | ||
832 | evdev_table[evdev->minor] = NULL; | ||
833 | mutex_unlock(&evdev_table_mutex); | ||
834 | } | ||
835 | |||
836 | /* | ||
837 | * Mark device non-existent. This disables writes, ioctls and | ||
838 | * prevents new users from opening the device. Already posted | ||
839 | * blocking reads will stay, however new ones will fail. | ||
840 | */ | ||
841 | static void evdev_mark_dead(struct evdev *evdev) | ||
842 | { | ||
843 | mutex_lock(&evdev->mutex); | ||
844 | evdev->exist = 0; | ||
845 | mutex_unlock(&evdev->mutex); | ||
846 | } | ||
847 | |||
848 | static void evdev_cleanup(struct evdev *evdev) | ||
849 | { | ||
850 | struct input_handle *handle = &evdev->handle; | ||
851 | |||
852 | evdev_mark_dead(evdev); | ||
853 | evdev_hangup(evdev); | ||
854 | evdev_remove_chrdev(evdev); | ||
855 | |||
856 | /* evdev is marked dead so no one else accesses evdev->open */ | ||
857 | if (evdev->open) { | ||
858 | input_flush_device(handle, NULL); | ||
859 | input_close_device(handle); | ||
860 | } | ||
861 | } | ||
862 | |||
863 | /* | ||
864 | * Create new evdev device. Note that input core serializes calls | ||
865 | * to connect and disconnect so we don't need to lock evdev_table here. | ||
866 | */ | ||
633 | static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | 867 | static int evdev_connect(struct input_handler *handler, struct input_dev *dev, |
634 | const struct input_device_id *id) | 868 | const struct input_device_id *id) |
635 | { | 869 | { |
@@ -637,7 +871,10 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
637 | int minor; | 871 | int minor; |
638 | int error; | 872 | int error; |
639 | 873 | ||
640 | for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); | 874 | for (minor = 0; minor < EVDEV_MINORS; minor++) |
875 | if (!evdev_table[minor]) | ||
876 | break; | ||
877 | |||
641 | if (minor == EVDEV_MINORS) { | 878 | if (minor == EVDEV_MINORS) { |
642 | printk(KERN_ERR "evdev: no more free evdev devices\n"); | 879 | printk(KERN_ERR "evdev: no more free evdev devices\n"); |
643 | return -ENFILE; | 880 | return -ENFILE; |
@@ -648,38 +885,44 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
648 | return -ENOMEM; | 885 | return -ENOMEM; |
649 | 886 | ||
650 | INIT_LIST_HEAD(&evdev->client_list); | 887 | INIT_LIST_HEAD(&evdev->client_list); |
888 | spin_lock_init(&evdev->client_lock); | ||
889 | mutex_init(&evdev->mutex); | ||
651 | init_waitqueue_head(&evdev->wait); | 890 | init_waitqueue_head(&evdev->wait); |
652 | 891 | ||
892 | snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); | ||
653 | evdev->exist = 1; | 893 | evdev->exist = 1; |
654 | evdev->minor = minor; | 894 | evdev->minor = minor; |
895 | |||
655 | evdev->handle.dev = dev; | 896 | evdev->handle.dev = dev; |
656 | evdev->handle.name = evdev->name; | 897 | evdev->handle.name = evdev->name; |
657 | evdev->handle.handler = handler; | 898 | evdev->handle.handler = handler; |
658 | evdev->handle.private = evdev; | 899 | evdev->handle.private = evdev; |
659 | snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); | ||
660 | 900 | ||
661 | snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id), | 901 | strlcpy(evdev->dev.bus_id, evdev->name, sizeof(evdev->dev.bus_id)); |
662 | "event%d", minor); | 902 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); |
663 | evdev->dev.class = &input_class; | 903 | evdev->dev.class = &input_class; |
664 | evdev->dev.parent = &dev->dev; | 904 | evdev->dev.parent = &dev->dev; |
665 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); | ||
666 | evdev->dev.release = evdev_free; | 905 | evdev->dev.release = evdev_free; |
667 | device_initialize(&evdev->dev); | 906 | device_initialize(&evdev->dev); |
668 | 907 | ||
669 | evdev_table[minor] = evdev; | 908 | error = input_register_handle(&evdev->handle); |
670 | |||
671 | error = device_add(&evdev->dev); | ||
672 | if (error) | 909 | if (error) |
673 | goto err_free_evdev; | 910 | goto err_free_evdev; |
674 | 911 | ||
675 | error = input_register_handle(&evdev->handle); | 912 | error = evdev_install_chrdev(evdev); |
913 | if (error) | ||
914 | goto err_unregister_handle; | ||
915 | |||
916 | error = device_add(&evdev->dev); | ||
676 | if (error) | 917 | if (error) |
677 | goto err_delete_evdev; | 918 | goto err_cleanup_evdev; |
678 | 919 | ||
679 | return 0; | 920 | return 0; |
680 | 921 | ||
681 | err_delete_evdev: | 922 | err_cleanup_evdev: |
682 | device_del(&evdev->dev); | 923 | evdev_cleanup(evdev); |
924 | err_unregister_handle: | ||
925 | input_unregister_handle(&evdev->handle); | ||
683 | err_free_evdev: | 926 | err_free_evdev: |
684 | put_device(&evdev->dev); | 927 | put_device(&evdev->dev); |
685 | return error; | 928 | return error; |
@@ -688,21 +931,10 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
688 | static void evdev_disconnect(struct input_handle *handle) | 931 | static void evdev_disconnect(struct input_handle *handle) |
689 | { | 932 | { |
690 | struct evdev *evdev = handle->private; | 933 | struct evdev *evdev = handle->private; |
691 | struct evdev_client *client; | ||
692 | 934 | ||
693 | input_unregister_handle(handle); | ||
694 | device_del(&evdev->dev); | 935 | device_del(&evdev->dev); |
695 | 936 | evdev_cleanup(evdev); | |
696 | evdev->exist = 0; | 937 | input_unregister_handle(handle); |
697 | |||
698 | if (evdev->open) { | ||
699 | input_flush_device(handle, NULL); | ||
700 | input_close_device(handle); | ||
701 | list_for_each_entry(client, &evdev->client_list, node) | ||
702 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
703 | wake_up_interruptible(&evdev->wait); | ||
704 | } | ||
705 | |||
706 | put_device(&evdev->dev); | 938 | put_device(&evdev->dev); |
707 | } | 939 | } |
708 | 940 | ||
@@ -714,13 +946,13 @@ static const struct input_device_id evdev_ids[] = { | |||
714 | MODULE_DEVICE_TABLE(input, evdev_ids); | 946 | MODULE_DEVICE_TABLE(input, evdev_ids); |
715 | 947 | ||
716 | static struct input_handler evdev_handler = { | 948 | static struct input_handler evdev_handler = { |
717 | .event = evdev_event, | 949 | .event = evdev_event, |
718 | .connect = evdev_connect, | 950 | .connect = evdev_connect, |
719 | .disconnect = evdev_disconnect, | 951 | .disconnect = evdev_disconnect, |
720 | .fops = &evdev_fops, | 952 | .fops = &evdev_fops, |
721 | .minor = EVDEV_MINOR_BASE, | 953 | .minor = EVDEV_MINOR_BASE, |
722 | .name = "evdev", | 954 | .name = "evdev", |
723 | .id_table = evdev_ids, | 955 | .id_table = evdev_ids, |
724 | }; | 956 | }; |
725 | 957 | ||
726 | static int __init evdev_init(void) | 958 | static int __init evdev_init(void) |
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index b773d4c756a6..92b359894e81 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c | |||
@@ -70,6 +70,7 @@ static int input_open_polled_device(struct input_dev *input) | |||
70 | { | 70 | { |
71 | struct input_polled_dev *dev = input->private; | 71 | struct input_polled_dev *dev = input->private; |
72 | int error; | 72 | int error; |
73 | unsigned long ticks; | ||
73 | 74 | ||
74 | error = input_polldev_start_workqueue(); | 75 | error = input_polldev_start_workqueue(); |
75 | if (error) | 76 | if (error) |
@@ -78,8 +79,10 @@ static int input_open_polled_device(struct input_dev *input) | |||
78 | if (dev->flush) | 79 | if (dev->flush) |
79 | dev->flush(dev); | 80 | dev->flush(dev); |
80 | 81 | ||
81 | queue_delayed_work(polldev_wq, &dev->work, | 82 | ticks = msecs_to_jiffies(dev->poll_interval); |
82 | msecs_to_jiffies(dev->poll_interval)); | 83 | if (ticks >= HZ) |
84 | ticks = round_jiffies(ticks); | ||
85 | queue_delayed_work(polldev_wq, &dev->work, ticks); | ||
83 | 86 | ||
84 | return 0; | 87 | return 0; |
85 | } | 88 | } |
diff --git a/drivers/input/input.c b/drivers/input/input.c index 5dc361c954e2..2f2b020cd629 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -17,10 +17,10 @@ | |||
17 | #include <linux/major.h> | 17 | #include <linux/major.h> |
18 | #include <linux/proc_fs.h> | 18 | #include <linux/proc_fs.h> |
19 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/poll.h> | 20 | #include <linux/poll.h> |
22 | #include <linux/device.h> | 21 | #include <linux/device.h> |
23 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/rcupdate.h> | ||
24 | 24 | ||
25 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | 25 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); |
26 | MODULE_DESCRIPTION("Input core"); | 26 | MODULE_DESCRIPTION("Input core"); |
@@ -31,167 +31,245 @@ MODULE_LICENSE("GPL"); | |||
31 | static LIST_HEAD(input_dev_list); | 31 | static LIST_HEAD(input_dev_list); |
32 | static LIST_HEAD(input_handler_list); | 32 | static LIST_HEAD(input_handler_list); |
33 | 33 | ||
34 | /* | ||
35 | * input_mutex protects access to both input_dev_list and input_handler_list. | ||
36 | * This also causes input_[un]register_device and input_[un]register_handler | ||
37 | * be mutually exclusive which simplifies locking in drivers implementing | ||
38 | * input handlers. | ||
39 | */ | ||
40 | static DEFINE_MUTEX(input_mutex); | ||
41 | |||
34 | static struct input_handler *input_table[8]; | 42 | static struct input_handler *input_table[8]; |
35 | 43 | ||
36 | /** | 44 | static inline int is_event_supported(unsigned int code, |
37 | * input_event() - report new input event | 45 | unsigned long *bm, unsigned int max) |
38 | * @dev: device that generated the event | ||
39 | * @type: type of the event | ||
40 | * @code: event code | ||
41 | * @value: value of the event | ||
42 | * | ||
43 | * This function should be used by drivers implementing various input devices | ||
44 | * See also input_inject_event() | ||
45 | */ | ||
46 | void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | ||
47 | { | 46 | { |
48 | struct input_handle *handle; | 47 | return code <= max && test_bit(code, bm); |
48 | } | ||
49 | 49 | ||
50 | if (type > EV_MAX || !test_bit(type, dev->evbit)) | 50 | static int input_defuzz_abs_event(int value, int old_val, int fuzz) |
51 | return; | 51 | { |
52 | if (fuzz) { | ||
53 | if (value > old_val - fuzz / 2 && value < old_val + fuzz / 2) | ||
54 | return old_val; | ||
52 | 55 | ||
53 | add_input_randomness(type, code, value); | 56 | if (value > old_val - fuzz && value < old_val + fuzz) |
57 | return (old_val * 3 + value) / 4; | ||
54 | 58 | ||
55 | switch (type) { | 59 | if (value > old_val - fuzz * 2 && value < old_val + fuzz * 2) |
56 | 60 | return (old_val + value) / 2; | |
57 | case EV_SYN: | 61 | } |
58 | switch (code) { | ||
59 | case SYN_CONFIG: | ||
60 | if (dev->event) | ||
61 | dev->event(dev, type, code, value); | ||
62 | break; | ||
63 | |||
64 | case SYN_REPORT: | ||
65 | if (dev->sync) | ||
66 | return; | ||
67 | dev->sync = 1; | ||
68 | break; | ||
69 | } | ||
70 | break; | ||
71 | 62 | ||
72 | case EV_KEY: | 63 | return value; |
64 | } | ||
73 | 65 | ||
74 | if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value) | 66 | /* |
75 | return; | 67 | * Pass event through all open handles. This function is called with |
68 | * dev->event_lock held and interrupts disabled. | ||
69 | */ | ||
70 | static void input_pass_event(struct input_dev *dev, | ||
71 | unsigned int type, unsigned int code, int value) | ||
72 | { | ||
73 | struct input_handle *handle; | ||
76 | 74 | ||
77 | if (value == 2) | 75 | rcu_read_lock(); |
78 | break; | ||
79 | 76 | ||
80 | change_bit(code, dev->key); | 77 | handle = rcu_dereference(dev->grab); |
78 | if (handle) | ||
79 | handle->handler->event(handle, type, code, value); | ||
80 | else | ||
81 | list_for_each_entry_rcu(handle, &dev->h_list, d_node) | ||
82 | if (handle->open) | ||
83 | handle->handler->event(handle, | ||
84 | type, code, value); | ||
85 | rcu_read_unlock(); | ||
86 | } | ||
81 | 87 | ||
82 | if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->timer.data && value) { | 88 | /* |
83 | dev->repeat_key = code; | 89 | * Generate software autorepeat event. Note that we take |
84 | mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); | 90 | * dev->event_lock here to avoid racing with input_event |
85 | } | 91 | * which may cause keys get "stuck". |
92 | */ | ||
93 | static void input_repeat_key(unsigned long data) | ||
94 | { | ||
95 | struct input_dev *dev = (void *) data; | ||
96 | unsigned long flags; | ||
86 | 97 | ||
87 | break; | 98 | spin_lock_irqsave(&dev->event_lock, flags); |
88 | 99 | ||
89 | case EV_SW: | 100 | if (test_bit(dev->repeat_key, dev->key) && |
101 | is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { | ||
90 | 102 | ||
91 | if (code > SW_MAX || !test_bit(code, dev->swbit) || !!test_bit(code, dev->sw) == value) | 103 | input_pass_event(dev, EV_KEY, dev->repeat_key, 2); |
92 | return; | ||
93 | 104 | ||
94 | change_bit(code, dev->sw); | 105 | if (dev->sync) { |
106 | /* | ||
107 | * Only send SYN_REPORT if we are not in a middle | ||
108 | * of driver parsing a new hardware packet. | ||
109 | * Otherwise assume that the driver will send | ||
110 | * SYN_REPORT once it's done. | ||
111 | */ | ||
112 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); | ||
113 | } | ||
95 | 114 | ||
96 | break; | 115 | if (dev->rep[REP_PERIOD]) |
116 | mod_timer(&dev->timer, jiffies + | ||
117 | msecs_to_jiffies(dev->rep[REP_PERIOD])); | ||
118 | } | ||
97 | 119 | ||
98 | case EV_ABS: | 120 | spin_unlock_irqrestore(&dev->event_lock, flags); |
121 | } | ||
99 | 122 | ||
100 | if (code > ABS_MAX || !test_bit(code, dev->absbit)) | 123 | static void input_start_autorepeat(struct input_dev *dev, int code) |
101 | return; | 124 | { |
125 | if (test_bit(EV_REP, dev->evbit) && | ||
126 | dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && | ||
127 | dev->timer.data) { | ||
128 | dev->repeat_key = code; | ||
129 | mod_timer(&dev->timer, | ||
130 | jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); | ||
131 | } | ||
132 | } | ||
102 | 133 | ||
103 | if (dev->absfuzz[code]) { | 134 | #define INPUT_IGNORE_EVENT 0 |
104 | if ((value > dev->abs[code] - (dev->absfuzz[code] >> 1)) && | 135 | #define INPUT_PASS_TO_HANDLERS 1 |
105 | (value < dev->abs[code] + (dev->absfuzz[code] >> 1))) | 136 | #define INPUT_PASS_TO_DEVICE 2 |
106 | return; | 137 | #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) |
107 | 138 | ||
108 | if ((value > dev->abs[code] - dev->absfuzz[code]) && | 139 | static void input_handle_event(struct input_dev *dev, |
109 | (value < dev->abs[code] + dev->absfuzz[code])) | 140 | unsigned int type, unsigned int code, int value) |
110 | value = (dev->abs[code] * 3 + value) >> 2; | 141 | { |
142 | int disposition = INPUT_IGNORE_EVENT; | ||
111 | 143 | ||
112 | if ((value > dev->abs[code] - (dev->absfuzz[code] << 1)) && | 144 | switch (type) { |
113 | (value < dev->abs[code] + (dev->absfuzz[code] << 1))) | ||
114 | value = (dev->abs[code] + value) >> 1; | ||
115 | } | ||
116 | 145 | ||
117 | if (dev->abs[code] == value) | 146 | case EV_SYN: |
118 | return; | 147 | switch (code) { |
148 | case SYN_CONFIG: | ||
149 | disposition = INPUT_PASS_TO_ALL; | ||
150 | break; | ||
119 | 151 | ||
120 | dev->abs[code] = value; | 152 | case SYN_REPORT: |
153 | if (!dev->sync) { | ||
154 | dev->sync = 1; | ||
155 | disposition = INPUT_PASS_TO_HANDLERS; | ||
156 | } | ||
121 | break; | 157 | break; |
158 | } | ||
159 | break; | ||
122 | 160 | ||
123 | case EV_REL: | 161 | case EV_KEY: |
162 | if (is_event_supported(code, dev->keybit, KEY_MAX) && | ||
163 | !!test_bit(code, dev->key) != value) { | ||
124 | 164 | ||
125 | if (code > REL_MAX || !test_bit(code, dev->relbit) || (value == 0)) | 165 | if (value != 2) { |
126 | return; | 166 | __change_bit(code, dev->key); |
167 | if (value) | ||
168 | input_start_autorepeat(dev, code); | ||
169 | } | ||
127 | 170 | ||
128 | break; | 171 | disposition = INPUT_PASS_TO_HANDLERS; |
172 | } | ||
173 | break; | ||
129 | 174 | ||
130 | case EV_MSC: | 175 | case EV_SW: |
176 | if (is_event_supported(code, dev->swbit, SW_MAX) && | ||
177 | !!test_bit(code, dev->sw) != value) { | ||
131 | 178 | ||
132 | if (code > MSC_MAX || !test_bit(code, dev->mscbit)) | 179 | __change_bit(code, dev->sw); |
133 | return; | 180 | disposition = INPUT_PASS_TO_HANDLERS; |
181 | } | ||
182 | break; | ||
134 | 183 | ||
135 | if (dev->event) | 184 | case EV_ABS: |
136 | dev->event(dev, type, code, value); | 185 | if (is_event_supported(code, dev->absbit, ABS_MAX)) { |
137 | 186 | ||
138 | break; | 187 | value = input_defuzz_abs_event(value, |
188 | dev->abs[code], dev->absfuzz[code]); | ||
189 | |||
190 | if (dev->abs[code] != value) { | ||
191 | dev->abs[code] = value; | ||
192 | disposition = INPUT_PASS_TO_HANDLERS; | ||
193 | } | ||
194 | } | ||
195 | break; | ||
139 | 196 | ||
140 | case EV_LED: | 197 | case EV_REL: |
198 | if (is_event_supported(code, dev->relbit, REL_MAX) && value) | ||
199 | disposition = INPUT_PASS_TO_HANDLERS; | ||
141 | 200 | ||
142 | if (code > LED_MAX || !test_bit(code, dev->ledbit) || !!test_bit(code, dev->led) == value) | 201 | break; |
143 | return; | ||
144 | 202 | ||
145 | change_bit(code, dev->led); | 203 | case EV_MSC: |
204 | if (is_event_supported(code, dev->mscbit, MSC_MAX)) | ||
205 | disposition = INPUT_PASS_TO_ALL; | ||
146 | 206 | ||
147 | if (dev->event) | 207 | break; |
148 | dev->event(dev, type, code, value); | ||
149 | 208 | ||
150 | break; | 209 | case EV_LED: |
210 | if (is_event_supported(code, dev->ledbit, LED_MAX) && | ||
211 | !!test_bit(code, dev->led) != value) { | ||
151 | 212 | ||
152 | case EV_SND: | 213 | __change_bit(code, dev->led); |
214 | disposition = INPUT_PASS_TO_ALL; | ||
215 | } | ||
216 | break; | ||
153 | 217 | ||
154 | if (code > SND_MAX || !test_bit(code, dev->sndbit)) | 218 | case EV_SND: |
155 | return; | 219 | if (is_event_supported(code, dev->sndbit, SND_MAX)) { |
156 | 220 | ||
157 | if (!!test_bit(code, dev->snd) != !!value) | 221 | if (!!test_bit(code, dev->snd) != !!value) |
158 | change_bit(code, dev->snd); | 222 | __change_bit(code, dev->snd); |
223 | disposition = INPUT_PASS_TO_ALL; | ||
224 | } | ||
225 | break; | ||
159 | 226 | ||
160 | if (dev->event) | 227 | case EV_REP: |
161 | dev->event(dev, type, code, value); | 228 | if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) { |
229 | dev->rep[code] = value; | ||
230 | disposition = INPUT_PASS_TO_ALL; | ||
231 | } | ||
232 | break; | ||
162 | 233 | ||
163 | break; | 234 | case EV_FF: |
235 | if (value >= 0) | ||
236 | disposition = INPUT_PASS_TO_ALL; | ||
237 | break; | ||
238 | } | ||
164 | 239 | ||
165 | case EV_REP: | 240 | if (type != EV_SYN) |
241 | dev->sync = 0; | ||
166 | 242 | ||
167 | if (code > REP_MAX || value < 0 || dev->rep[code] == value) | 243 | if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) |
168 | return; | 244 | dev->event(dev, type, code, value); |
169 | 245 | ||
170 | dev->rep[code] = value; | 246 | if (disposition & INPUT_PASS_TO_HANDLERS) |
171 | if (dev->event) | 247 | input_pass_event(dev, type, code, value); |
172 | dev->event(dev, type, code, value); | 248 | } |
173 | 249 | ||
174 | break; | 250 | /** |
251 | * input_event() - report new input event | ||
252 | * @dev: device that generated the event | ||
253 | * @type: type of the event | ||
254 | * @code: event code | ||
255 | * @value: value of the event | ||
256 | * | ||
257 | * This function should be used by drivers implementing various input | ||
258 | * devices. See also input_inject_event(). | ||
259 | */ | ||
175 | 260 | ||
176 | case EV_FF: | 261 | void input_event(struct input_dev *dev, |
262 | unsigned int type, unsigned int code, int value) | ||
263 | { | ||
264 | unsigned long flags; | ||
177 | 265 | ||
178 | if (value < 0) | 266 | if (is_event_supported(type, dev->evbit, EV_MAX)) { |
179 | return; | ||
180 | 267 | ||
181 | if (dev->event) | 268 | spin_lock_irqsave(&dev->event_lock, flags); |
182 | dev->event(dev, type, code, value); | 269 | add_input_randomness(type, code, value); |
183 | break; | 270 | input_handle_event(dev, type, code, value); |
271 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
184 | } | 272 | } |
185 | |||
186 | if (type != EV_SYN) | ||
187 | dev->sync = 0; | ||
188 | |||
189 | if (dev->grab) | ||
190 | dev->grab->handler->event(dev->grab, type, code, value); | ||
191 | else | ||
192 | list_for_each_entry(handle, &dev->h_list, d_node) | ||
193 | if (handle->open) | ||
194 | handle->handler->event(handle, type, code, value); | ||
195 | } | 273 | } |
196 | EXPORT_SYMBOL(input_event); | 274 | EXPORT_SYMBOL(input_event); |
197 | 275 | ||
@@ -202,102 +280,228 @@ EXPORT_SYMBOL(input_event); | |||
202 | * @code: event code | 280 | * @code: event code |
203 | * @value: value of the event | 281 | * @value: value of the event |
204 | * | 282 | * |
205 | * Similar to input_event() but will ignore event if device is "grabbed" and handle | 283 | * Similar to input_event() but will ignore event if device is |
206 | * injecting event is not the one that owns the device. | 284 | * "grabbed" and handle injecting event is not the one that owns |
285 | * the device. | ||
207 | */ | 286 | */ |
208 | void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 287 | void input_inject_event(struct input_handle *handle, |
209 | { | 288 | unsigned int type, unsigned int code, int value) |
210 | if (!handle->dev->grab || handle->dev->grab == handle) | ||
211 | input_event(handle->dev, type, code, value); | ||
212 | } | ||
213 | EXPORT_SYMBOL(input_inject_event); | ||
214 | |||
215 | static void input_repeat_key(unsigned long data) | ||
216 | { | 289 | { |
217 | struct input_dev *dev = (void *) data; | 290 | struct input_dev *dev = handle->dev; |
291 | struct input_handle *grab; | ||
292 | unsigned long flags; | ||
218 | 293 | ||
219 | if (!test_bit(dev->repeat_key, dev->key)) | 294 | if (is_event_supported(type, dev->evbit, EV_MAX)) { |
220 | return; | 295 | spin_lock_irqsave(&dev->event_lock, flags); |
221 | 296 | ||
222 | input_event(dev, EV_KEY, dev->repeat_key, 2); | 297 | rcu_read_lock(); |
223 | input_sync(dev); | 298 | grab = rcu_dereference(dev->grab); |
299 | if (!grab || grab == handle) | ||
300 | input_handle_event(dev, type, code, value); | ||
301 | rcu_read_unlock(); | ||
224 | 302 | ||
225 | if (dev->rep[REP_PERIOD]) | 303 | spin_unlock_irqrestore(&dev->event_lock, flags); |
226 | mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD])); | 304 | } |
227 | } | 305 | } |
306 | EXPORT_SYMBOL(input_inject_event); | ||
228 | 307 | ||
308 | /** | ||
309 | * input_grab_device - grabs device for exclusive use | ||
310 | * @handle: input handle that wants to own the device | ||
311 | * | ||
312 | * When a device is grabbed by an input handle all events generated by | ||
313 | * the device are delivered only to this handle. Also events injected | ||
314 | * by other input handles are ignored while device is grabbed. | ||
315 | */ | ||
229 | int input_grab_device(struct input_handle *handle) | 316 | int input_grab_device(struct input_handle *handle) |
230 | { | 317 | { |
231 | if (handle->dev->grab) | 318 | struct input_dev *dev = handle->dev; |
232 | return -EBUSY; | 319 | int retval; |
233 | 320 | ||
234 | handle->dev->grab = handle; | 321 | retval = mutex_lock_interruptible(&dev->mutex); |
235 | return 0; | 322 | if (retval) |
323 | return retval; | ||
324 | |||
325 | if (dev->grab) { | ||
326 | retval = -EBUSY; | ||
327 | goto out; | ||
328 | } | ||
329 | |||
330 | rcu_assign_pointer(dev->grab, handle); | ||
331 | synchronize_rcu(); | ||
332 | |||
333 | out: | ||
334 | mutex_unlock(&dev->mutex); | ||
335 | return retval; | ||
236 | } | 336 | } |
237 | EXPORT_SYMBOL(input_grab_device); | 337 | EXPORT_SYMBOL(input_grab_device); |
238 | 338 | ||
239 | void input_release_device(struct input_handle *handle) | 339 | static void __input_release_device(struct input_handle *handle) |
240 | { | 340 | { |
241 | struct input_dev *dev = handle->dev; | 341 | struct input_dev *dev = handle->dev; |
242 | 342 | ||
243 | if (dev->grab == handle) { | 343 | if (dev->grab == handle) { |
244 | dev->grab = NULL; | 344 | rcu_assign_pointer(dev->grab, NULL); |
345 | /* Make sure input_pass_event() notices that grab is gone */ | ||
346 | synchronize_rcu(); | ||
245 | 347 | ||
246 | list_for_each_entry(handle, &dev->h_list, d_node) | 348 | list_for_each_entry(handle, &dev->h_list, d_node) |
247 | if (handle->handler->start) | 349 | if (handle->open && handle->handler->start) |
248 | handle->handler->start(handle); | 350 | handle->handler->start(handle); |
249 | } | 351 | } |
250 | } | 352 | } |
353 | |||
354 | /** | ||
355 | * input_release_device - release previously grabbed device | ||
356 | * @handle: input handle that owns the device | ||
357 | * | ||
358 | * Releases previously grabbed device so that other input handles can | ||
359 | * start receiving input events. Upon release all handlers attached | ||
360 | * to the device have their start() method called so they have a change | ||
361 | * to synchronize device state with the rest of the system. | ||
362 | */ | ||
363 | void input_release_device(struct input_handle *handle) | ||
364 | { | ||
365 | struct input_dev *dev = handle->dev; | ||
366 | |||
367 | mutex_lock(&dev->mutex); | ||
368 | __input_release_device(handle); | ||
369 | mutex_unlock(&dev->mutex); | ||
370 | } | ||
251 | EXPORT_SYMBOL(input_release_device); | 371 | EXPORT_SYMBOL(input_release_device); |
252 | 372 | ||
373 | /** | ||
374 | * input_open_device - open input device | ||
375 | * @handle: handle through which device is being accessed | ||
376 | * | ||
377 | * This function should be called by input handlers when they | ||
378 | * want to start receive events from given input device. | ||
379 | */ | ||
253 | int input_open_device(struct input_handle *handle) | 380 | int input_open_device(struct input_handle *handle) |
254 | { | 381 | { |
255 | struct input_dev *dev = handle->dev; | 382 | struct input_dev *dev = handle->dev; |
256 | int err; | 383 | int retval; |
257 | 384 | ||
258 | err = mutex_lock_interruptible(&dev->mutex); | 385 | retval = mutex_lock_interruptible(&dev->mutex); |
259 | if (err) | 386 | if (retval) |
260 | return err; | 387 | return retval; |
388 | |||
389 | if (dev->going_away) { | ||
390 | retval = -ENODEV; | ||
391 | goto out; | ||
392 | } | ||
261 | 393 | ||
262 | handle->open++; | 394 | handle->open++; |
263 | 395 | ||
264 | if (!dev->users++ && dev->open) | 396 | if (!dev->users++ && dev->open) |
265 | err = dev->open(dev); | 397 | retval = dev->open(dev); |
266 | 398 | ||
267 | if (err) | 399 | if (retval) { |
268 | handle->open--; | 400 | dev->users--; |
401 | if (!--handle->open) { | ||
402 | /* | ||
403 | * Make sure we are not delivering any more events | ||
404 | * through this handle | ||
405 | */ | ||
406 | synchronize_rcu(); | ||
407 | } | ||
408 | } | ||
269 | 409 | ||
410 | out: | ||
270 | mutex_unlock(&dev->mutex); | 411 | mutex_unlock(&dev->mutex); |
271 | 412 | return retval; | |
272 | return err; | ||
273 | } | 413 | } |
274 | EXPORT_SYMBOL(input_open_device); | 414 | EXPORT_SYMBOL(input_open_device); |
275 | 415 | ||
276 | int input_flush_device(struct input_handle* handle, struct file* file) | 416 | int input_flush_device(struct input_handle *handle, struct file *file) |
277 | { | 417 | { |
278 | if (handle->dev->flush) | 418 | struct input_dev *dev = handle->dev; |
279 | return handle->dev->flush(handle->dev, file); | 419 | int retval; |
280 | 420 | ||
281 | return 0; | 421 | retval = mutex_lock_interruptible(&dev->mutex); |
422 | if (retval) | ||
423 | return retval; | ||
424 | |||
425 | if (dev->flush) | ||
426 | retval = dev->flush(dev, file); | ||
427 | |||
428 | mutex_unlock(&dev->mutex); | ||
429 | return retval; | ||
282 | } | 430 | } |
283 | EXPORT_SYMBOL(input_flush_device); | 431 | EXPORT_SYMBOL(input_flush_device); |
284 | 432 | ||
433 | /** | ||
434 | * input_close_device - close input device | ||
435 | * @handle: handle through which device is being accessed | ||
436 | * | ||
437 | * This function should be called by input handlers when they | ||
438 | * want to stop receive events from given input device. | ||
439 | */ | ||
285 | void input_close_device(struct input_handle *handle) | 440 | void input_close_device(struct input_handle *handle) |
286 | { | 441 | { |
287 | struct input_dev *dev = handle->dev; | 442 | struct input_dev *dev = handle->dev; |
288 | 443 | ||
289 | input_release_device(handle); | ||
290 | |||
291 | mutex_lock(&dev->mutex); | 444 | mutex_lock(&dev->mutex); |
292 | 445 | ||
446 | __input_release_device(handle); | ||
447 | |||
293 | if (!--dev->users && dev->close) | 448 | if (!--dev->users && dev->close) |
294 | dev->close(dev); | 449 | dev->close(dev); |
295 | handle->open--; | 450 | |
451 | if (!--handle->open) { | ||
452 | /* | ||
453 | * synchronize_rcu() makes sure that input_pass_event() | ||
454 | * completed and that no more input events are delivered | ||
455 | * through this handle | ||
456 | */ | ||
457 | synchronize_rcu(); | ||
458 | } | ||
296 | 459 | ||
297 | mutex_unlock(&dev->mutex); | 460 | mutex_unlock(&dev->mutex); |
298 | } | 461 | } |
299 | EXPORT_SYMBOL(input_close_device); | 462 | EXPORT_SYMBOL(input_close_device); |
300 | 463 | ||
464 | /* | ||
465 | * Prepare device for unregistering | ||
466 | */ | ||
467 | static void input_disconnect_device(struct input_dev *dev) | ||
468 | { | ||
469 | struct input_handle *handle; | ||
470 | int code; | ||
471 | |||
472 | /* | ||
473 | * Mark device as going away. Note that we take dev->mutex here | ||
474 | * not to protect access to dev->going_away but rather to ensure | ||
475 | * that there are no threads in the middle of input_open_device() | ||
476 | */ | ||
477 | mutex_lock(&dev->mutex); | ||
478 | dev->going_away = 1; | ||
479 | mutex_unlock(&dev->mutex); | ||
480 | |||
481 | spin_lock_irq(&dev->event_lock); | ||
482 | |||
483 | /* | ||
484 | * Simulate keyup events for all pressed keys so that handlers | ||
485 | * are not left with "stuck" keys. The driver may continue | ||
486 | * generate events even after we done here but they will not | ||
487 | * reach any handlers. | ||
488 | */ | ||
489 | if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { | ||
490 | for (code = 0; code <= KEY_MAX; code++) { | ||
491 | if (is_event_supported(code, dev->keybit, KEY_MAX) && | ||
492 | test_bit(code, dev->key)) { | ||
493 | input_pass_event(dev, EV_KEY, code, 0); | ||
494 | } | ||
495 | } | ||
496 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); | ||
497 | } | ||
498 | |||
499 | list_for_each_entry(handle, &dev->h_list, d_node) | ||
500 | handle->open = 0; | ||
501 | |||
502 | spin_unlock_irq(&dev->event_lock); | ||
503 | } | ||
504 | |||
301 | static int input_fetch_keycode(struct input_dev *dev, int scancode) | 505 | static int input_fetch_keycode(struct input_dev *dev, int scancode) |
302 | { | 506 | { |
303 | switch (dev->keycodesize) { | 507 | switch (dev->keycodesize) { |
@@ -473,7 +677,8 @@ static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait) | |||
473 | 677 | ||
474 | static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos) | 678 | static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos) |
475 | { | 679 | { |
476 | /* acquire lock here ... Yes, we do need locking, I knowi, I know... */ | 680 | if (mutex_lock_interruptible(&input_mutex)) |
681 | return NULL; | ||
477 | 682 | ||
478 | return seq_list_start(&input_dev_list, *pos); | 683 | return seq_list_start(&input_dev_list, *pos); |
479 | } | 684 | } |
@@ -485,7 +690,7 @@ static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
485 | 690 | ||
486 | static void input_devices_seq_stop(struct seq_file *seq, void *v) | 691 | static void input_devices_seq_stop(struct seq_file *seq, void *v) |
487 | { | 692 | { |
488 | /* release lock here */ | 693 | mutex_unlock(&input_mutex); |
489 | } | 694 | } |
490 | 695 | ||
491 | static void input_seq_print_bitmap(struct seq_file *seq, const char *name, | 696 | static void input_seq_print_bitmap(struct seq_file *seq, const char *name, |
@@ -569,7 +774,9 @@ static const struct file_operations input_devices_fileops = { | |||
569 | 774 | ||
570 | static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) | 775 | static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) |
571 | { | 776 | { |
572 | /* acquire lock here ... Yes, we do need locking, I knowi, I know... */ | 777 | if (mutex_lock_interruptible(&input_mutex)) |
778 | return NULL; | ||
779 | |||
573 | seq->private = (void *)(unsigned long)*pos; | 780 | seq->private = (void *)(unsigned long)*pos; |
574 | return seq_list_start(&input_handler_list, *pos); | 781 | return seq_list_start(&input_handler_list, *pos); |
575 | } | 782 | } |
@@ -582,7 +789,7 @@ static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
582 | 789 | ||
583 | static void input_handlers_seq_stop(struct seq_file *seq, void *v) | 790 | static void input_handlers_seq_stop(struct seq_file *seq, void *v) |
584 | { | 791 | { |
585 | /* release lock here */ | 792 | mutex_unlock(&input_mutex); |
586 | } | 793 | } |
587 | 794 | ||
588 | static int input_handlers_seq_show(struct seq_file *seq, void *v) | 795 | static int input_handlers_seq_show(struct seq_file *seq, void *v) |
@@ -983,6 +1190,7 @@ struct input_dev *input_allocate_device(void) | |||
983 | dev->dev.class = &input_class; | 1190 | dev->dev.class = &input_class; |
984 | device_initialize(&dev->dev); | 1191 | device_initialize(&dev->dev); |
985 | mutex_init(&dev->mutex); | 1192 | mutex_init(&dev->mutex); |
1193 | spin_lock_init(&dev->event_lock); | ||
986 | INIT_LIST_HEAD(&dev->h_list); | 1194 | INIT_LIST_HEAD(&dev->h_list); |
987 | INIT_LIST_HEAD(&dev->node); | 1195 | INIT_LIST_HEAD(&dev->node); |
988 | 1196 | ||
@@ -1000,7 +1208,7 @@ EXPORT_SYMBOL(input_allocate_device); | |||
1000 | * This function should only be used if input_register_device() | 1208 | * This function should only be used if input_register_device() |
1001 | * was not called yet or if it failed. Once device was registered | 1209 | * was not called yet or if it failed. Once device was registered |
1002 | * use input_unregister_device() and memory will be freed once last | 1210 | * use input_unregister_device() and memory will be freed once last |
1003 | * refrence to the device is dropped. | 1211 | * reference to the device is dropped. |
1004 | * | 1212 | * |
1005 | * Device should be allocated by input_allocate_device(). | 1213 | * Device should be allocated by input_allocate_device(). |
1006 | * | 1214 | * |
@@ -1070,6 +1278,18 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int | |||
1070 | } | 1278 | } |
1071 | EXPORT_SYMBOL(input_set_capability); | 1279 | EXPORT_SYMBOL(input_set_capability); |
1072 | 1280 | ||
1281 | /** | ||
1282 | * input_register_device - register device with input core | ||
1283 | * @dev: device to be registered | ||
1284 | * | ||
1285 | * This function registers device with input core. The device must be | ||
1286 | * allocated with input_allocate_device() and all it's capabilities | ||
1287 | * set up before registering. | ||
1288 | * If function fails the device must be freed with input_free_device(). | ||
1289 | * Once device has been successfully registered it can be unregistered | ||
1290 | * with input_unregister_device(); input_free_device() should not be | ||
1291 | * called in this case. | ||
1292 | */ | ||
1073 | int input_register_device(struct input_dev *dev) | 1293 | int input_register_device(struct input_dev *dev) |
1074 | { | 1294 | { |
1075 | static atomic_t input_no = ATOMIC_INIT(0); | 1295 | static atomic_t input_no = ATOMIC_INIT(0); |
@@ -1077,7 +1297,7 @@ int input_register_device(struct input_dev *dev) | |||
1077 | const char *path; | 1297 | const char *path; |
1078 | int error; | 1298 | int error; |
1079 | 1299 | ||
1080 | set_bit(EV_SYN, dev->evbit); | 1300 | __set_bit(EV_SYN, dev->evbit); |
1081 | 1301 | ||
1082 | /* | 1302 | /* |
1083 | * If delay and period are pre-set by the driver, then autorepeating | 1303 | * If delay and period are pre-set by the driver, then autorepeating |
@@ -1098,8 +1318,6 @@ int input_register_device(struct input_dev *dev) | |||
1098 | if (!dev->setkeycode) | 1318 | if (!dev->setkeycode) |
1099 | dev->setkeycode = input_default_setkeycode; | 1319 | dev->setkeycode = input_default_setkeycode; |
1100 | 1320 | ||
1101 | list_add_tail(&dev->node, &input_dev_list); | ||
1102 | |||
1103 | snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), | 1321 | snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), |
1104 | "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); | 1322 | "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); |
1105 | 1323 | ||
@@ -1115,49 +1333,79 @@ int input_register_device(struct input_dev *dev) | |||
1115 | dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); | 1333 | dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); |
1116 | kfree(path); | 1334 | kfree(path); |
1117 | 1335 | ||
1336 | error = mutex_lock_interruptible(&input_mutex); | ||
1337 | if (error) { | ||
1338 | device_del(&dev->dev); | ||
1339 | return error; | ||
1340 | } | ||
1341 | |||
1342 | list_add_tail(&dev->node, &input_dev_list); | ||
1343 | |||
1118 | list_for_each_entry(handler, &input_handler_list, node) | 1344 | list_for_each_entry(handler, &input_handler_list, node) |
1119 | input_attach_handler(dev, handler); | 1345 | input_attach_handler(dev, handler); |
1120 | 1346 | ||
1121 | input_wakeup_procfs_readers(); | 1347 | input_wakeup_procfs_readers(); |
1122 | 1348 | ||
1349 | mutex_unlock(&input_mutex); | ||
1350 | |||
1123 | return 0; | 1351 | return 0; |
1124 | } | 1352 | } |
1125 | EXPORT_SYMBOL(input_register_device); | 1353 | EXPORT_SYMBOL(input_register_device); |
1126 | 1354 | ||
1355 | /** | ||
1356 | * input_unregister_device - unregister previously registered device | ||
1357 | * @dev: device to be unregistered | ||
1358 | * | ||
1359 | * This function unregisters an input device. Once device is unregistered | ||
1360 | * the caller should not try to access it as it may get freed at any moment. | ||
1361 | */ | ||
1127 | void input_unregister_device(struct input_dev *dev) | 1362 | void input_unregister_device(struct input_dev *dev) |
1128 | { | 1363 | { |
1129 | struct input_handle *handle, *next; | 1364 | struct input_handle *handle, *next; |
1130 | int code; | ||
1131 | 1365 | ||
1132 | for (code = 0; code <= KEY_MAX; code++) | 1366 | input_disconnect_device(dev); |
1133 | if (test_bit(code, dev->key)) | ||
1134 | input_report_key(dev, code, 0); | ||
1135 | input_sync(dev); | ||
1136 | 1367 | ||
1137 | del_timer_sync(&dev->timer); | 1368 | mutex_lock(&input_mutex); |
1138 | 1369 | ||
1139 | list_for_each_entry_safe(handle, next, &dev->h_list, d_node) | 1370 | list_for_each_entry_safe(handle, next, &dev->h_list, d_node) |
1140 | handle->handler->disconnect(handle); | 1371 | handle->handler->disconnect(handle); |
1141 | WARN_ON(!list_empty(&dev->h_list)); | 1372 | WARN_ON(!list_empty(&dev->h_list)); |
1142 | 1373 | ||
1374 | del_timer_sync(&dev->timer); | ||
1143 | list_del_init(&dev->node); | 1375 | list_del_init(&dev->node); |
1144 | 1376 | ||
1145 | device_unregister(&dev->dev); | ||
1146 | |||
1147 | input_wakeup_procfs_readers(); | 1377 | input_wakeup_procfs_readers(); |
1378 | |||
1379 | mutex_unlock(&input_mutex); | ||
1380 | |||
1381 | device_unregister(&dev->dev); | ||
1148 | } | 1382 | } |
1149 | EXPORT_SYMBOL(input_unregister_device); | 1383 | EXPORT_SYMBOL(input_unregister_device); |
1150 | 1384 | ||
1385 | /** | ||
1386 | * input_register_handler - register a new input handler | ||
1387 | * @handler: handler to be registered | ||
1388 | * | ||
1389 | * This function registers a new input handler (interface) for input | ||
1390 | * devices in the system and attaches it to all input devices that | ||
1391 | * are compatible with the handler. | ||
1392 | */ | ||
1151 | int input_register_handler(struct input_handler *handler) | 1393 | int input_register_handler(struct input_handler *handler) |
1152 | { | 1394 | { |
1153 | struct input_dev *dev; | 1395 | struct input_dev *dev; |
1396 | int retval; | ||
1397 | |||
1398 | retval = mutex_lock_interruptible(&input_mutex); | ||
1399 | if (retval) | ||
1400 | return retval; | ||
1154 | 1401 | ||
1155 | INIT_LIST_HEAD(&handler->h_list); | 1402 | INIT_LIST_HEAD(&handler->h_list); |
1156 | 1403 | ||
1157 | if (handler->fops != NULL) { | 1404 | if (handler->fops != NULL) { |
1158 | if (input_table[handler->minor >> 5]) | 1405 | if (input_table[handler->minor >> 5]) { |
1159 | return -EBUSY; | 1406 | retval = -EBUSY; |
1160 | 1407 | goto out; | |
1408 | } | ||
1161 | input_table[handler->minor >> 5] = handler; | 1409 | input_table[handler->minor >> 5] = handler; |
1162 | } | 1410 | } |
1163 | 1411 | ||
@@ -1167,14 +1415,26 @@ int input_register_handler(struct input_handler *handler) | |||
1167 | input_attach_handler(dev, handler); | 1415 | input_attach_handler(dev, handler); |
1168 | 1416 | ||
1169 | input_wakeup_procfs_readers(); | 1417 | input_wakeup_procfs_readers(); |
1170 | return 0; | 1418 | |
1419 | out: | ||
1420 | mutex_unlock(&input_mutex); | ||
1421 | return retval; | ||
1171 | } | 1422 | } |
1172 | EXPORT_SYMBOL(input_register_handler); | 1423 | EXPORT_SYMBOL(input_register_handler); |
1173 | 1424 | ||
1425 | /** | ||
1426 | * input_unregister_handler - unregisters an input handler | ||
1427 | * @handler: handler to be unregistered | ||
1428 | * | ||
1429 | * This function disconnects a handler from its input devices and | ||
1430 | * removes it from lists of known handlers. | ||
1431 | */ | ||
1174 | void input_unregister_handler(struct input_handler *handler) | 1432 | void input_unregister_handler(struct input_handler *handler) |
1175 | { | 1433 | { |
1176 | struct input_handle *handle, *next; | 1434 | struct input_handle *handle, *next; |
1177 | 1435 | ||
1436 | mutex_lock(&input_mutex); | ||
1437 | |||
1178 | list_for_each_entry_safe(handle, next, &handler->h_list, h_node) | 1438 | list_for_each_entry_safe(handle, next, &handler->h_list, h_node) |
1179 | handler->disconnect(handle); | 1439 | handler->disconnect(handle); |
1180 | WARN_ON(!list_empty(&handler->h_list)); | 1440 | WARN_ON(!list_empty(&handler->h_list)); |
@@ -1185,14 +1445,45 @@ void input_unregister_handler(struct input_handler *handler) | |||
1185 | input_table[handler->minor >> 5] = NULL; | 1445 | input_table[handler->minor >> 5] = NULL; |
1186 | 1446 | ||
1187 | input_wakeup_procfs_readers(); | 1447 | input_wakeup_procfs_readers(); |
1448 | |||
1449 | mutex_unlock(&input_mutex); | ||
1188 | } | 1450 | } |
1189 | EXPORT_SYMBOL(input_unregister_handler); | 1451 | EXPORT_SYMBOL(input_unregister_handler); |
1190 | 1452 | ||
1453 | /** | ||
1454 | * input_register_handle - register a new input handle | ||
1455 | * @handle: handle to register | ||
1456 | * | ||
1457 | * This function puts a new input handle onto device's | ||
1458 | * and handler's lists so that events can flow through | ||
1459 | * it once it is opened using input_open_device(). | ||
1460 | * | ||
1461 | * This function is supposed to be called from handler's | ||
1462 | * connect() method. | ||
1463 | */ | ||
1191 | int input_register_handle(struct input_handle *handle) | 1464 | int input_register_handle(struct input_handle *handle) |
1192 | { | 1465 | { |
1193 | struct input_handler *handler = handle->handler; | 1466 | struct input_handler *handler = handle->handler; |
1467 | struct input_dev *dev = handle->dev; | ||
1468 | int error; | ||
1469 | |||
1470 | /* | ||
1471 | * We take dev->mutex here to prevent race with | ||
1472 | * input_release_device(). | ||
1473 | */ | ||
1474 | error = mutex_lock_interruptible(&dev->mutex); | ||
1475 | if (error) | ||
1476 | return error; | ||
1477 | list_add_tail_rcu(&handle->d_node, &dev->h_list); | ||
1478 | mutex_unlock(&dev->mutex); | ||
1479 | synchronize_rcu(); | ||
1194 | 1480 | ||
1195 | list_add_tail(&handle->d_node, &handle->dev->h_list); | 1481 | /* |
1482 | * Since we are supposed to be called from ->connect() | ||
1483 | * which is mutually exclusive with ->disconnect() | ||
1484 | * we can't be racing with input_unregister_handle() | ||
1485 | * and so separate lock is not needed here. | ||
1486 | */ | ||
1196 | list_add_tail(&handle->h_node, &handler->h_list); | 1487 | list_add_tail(&handle->h_node, &handler->h_list); |
1197 | 1488 | ||
1198 | if (handler->start) | 1489 | if (handler->start) |
@@ -1202,10 +1493,29 @@ int input_register_handle(struct input_handle *handle) | |||
1202 | } | 1493 | } |
1203 | EXPORT_SYMBOL(input_register_handle); | 1494 | EXPORT_SYMBOL(input_register_handle); |
1204 | 1495 | ||
1496 | /** | ||
1497 | * input_unregister_handle - unregister an input handle | ||
1498 | * @handle: handle to unregister | ||
1499 | * | ||
1500 | * This function removes input handle from device's | ||
1501 | * and handler's lists. | ||
1502 | * | ||
1503 | * This function is supposed to be called from handler's | ||
1504 | * disconnect() method. | ||
1505 | */ | ||
1205 | void input_unregister_handle(struct input_handle *handle) | 1506 | void input_unregister_handle(struct input_handle *handle) |
1206 | { | 1507 | { |
1508 | struct input_dev *dev = handle->dev; | ||
1509 | |||
1207 | list_del_init(&handle->h_node); | 1510 | list_del_init(&handle->h_node); |
1208 | list_del_init(&handle->d_node); | 1511 | |
1512 | /* | ||
1513 | * Take dev->mutex to prevent race with input_release_device(). | ||
1514 | */ | ||
1515 | mutex_lock(&dev->mutex); | ||
1516 | list_del_rcu(&handle->d_node); | ||
1517 | mutex_unlock(&dev->mutex); | ||
1518 | synchronize_rcu(); | ||
1209 | } | 1519 | } |
1210 | EXPORT_SYMBOL(input_unregister_handle); | 1520 | EXPORT_SYMBOL(input_unregister_handle); |
1211 | 1521 | ||
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index a9a0180bfd46..2b201f9aa024 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -43,6 +43,8 @@ struct joydev { | |||
43 | struct input_handle handle; | 43 | struct input_handle handle; |
44 | wait_queue_head_t wait; | 44 | wait_queue_head_t wait; |
45 | struct list_head client_list; | 45 | struct list_head client_list; |
46 | spinlock_t client_lock; /* protects client_list */ | ||
47 | struct mutex mutex; | ||
46 | struct device dev; | 48 | struct device dev; |
47 | 49 | ||
48 | struct js_corr corr[ABS_MAX + 1]; | 50 | struct js_corr corr[ABS_MAX + 1]; |
@@ -61,31 +63,61 @@ struct joydev_client { | |||
61 | int head; | 63 | int head; |
62 | int tail; | 64 | int tail; |
63 | int startup; | 65 | int startup; |
66 | spinlock_t buffer_lock; /* protects access to buffer, head and tail */ | ||
64 | struct fasync_struct *fasync; | 67 | struct fasync_struct *fasync; |
65 | struct joydev *joydev; | 68 | struct joydev *joydev; |
66 | struct list_head node; | 69 | struct list_head node; |
67 | }; | 70 | }; |
68 | 71 | ||
69 | static struct joydev *joydev_table[JOYDEV_MINORS]; | 72 | static struct joydev *joydev_table[JOYDEV_MINORS]; |
73 | static DEFINE_MUTEX(joydev_table_mutex); | ||
70 | 74 | ||
71 | static int joydev_correct(int value, struct js_corr *corr) | 75 | static int joydev_correct(int value, struct js_corr *corr) |
72 | { | 76 | { |
73 | switch (corr->type) { | 77 | switch (corr->type) { |
74 | case JS_CORR_NONE: | 78 | |
75 | break; | 79 | case JS_CORR_NONE: |
76 | case JS_CORR_BROKEN: | 80 | break; |
77 | value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 : | 81 | |
78 | ((corr->coef[3] * (value - corr->coef[1])) >> 14)) : | 82 | case JS_CORR_BROKEN: |
79 | ((corr->coef[2] * (value - corr->coef[0])) >> 14); | 83 | value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 : |
80 | break; | 84 | ((corr->coef[3] * (value - corr->coef[1])) >> 14)) : |
81 | default: | 85 | ((corr->coef[2] * (value - corr->coef[0])) >> 14); |
82 | return 0; | 86 | break; |
87 | |||
88 | default: | ||
89 | return 0; | ||
83 | } | 90 | } |
84 | 91 | ||
85 | return value < -32767 ? -32767 : (value > 32767 ? 32767 : value); | 92 | return value < -32767 ? -32767 : (value > 32767 ? 32767 : value); |
86 | } | 93 | } |
87 | 94 | ||
88 | static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 95 | static void joydev_pass_event(struct joydev_client *client, |
96 | struct js_event *event) | ||
97 | { | ||
98 | struct joydev *joydev = client->joydev; | ||
99 | |||
100 | /* | ||
101 | * IRQs already disabled, just acquire the lock | ||
102 | */ | ||
103 | spin_lock(&client->buffer_lock); | ||
104 | |||
105 | client->buffer[client->head] = *event; | ||
106 | |||
107 | if (client->startup == joydev->nabs + joydev->nkey) { | ||
108 | client->head++; | ||
109 | client->head &= JOYDEV_BUFFER_SIZE - 1; | ||
110 | if (client->tail == client->head) | ||
111 | client->startup = 0; | ||
112 | } | ||
113 | |||
114 | spin_unlock(&client->buffer_lock); | ||
115 | |||
116 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
117 | } | ||
118 | |||
119 | static void joydev_event(struct input_handle *handle, | ||
120 | unsigned int type, unsigned int code, int value) | ||
89 | { | 121 | { |
90 | struct joydev *joydev = handle->private; | 122 | struct joydev *joydev = handle->private; |
91 | struct joydev_client *client; | 123 | struct joydev_client *client; |
@@ -93,39 +125,34 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne | |||
93 | 125 | ||
94 | switch (type) { | 126 | switch (type) { |
95 | 127 | ||
96 | case EV_KEY: | 128 | case EV_KEY: |
97 | if (code < BTN_MISC || value == 2) | 129 | if (code < BTN_MISC || value == 2) |
98 | return; | 130 | return; |
99 | event.type = JS_EVENT_BUTTON; | 131 | event.type = JS_EVENT_BUTTON; |
100 | event.number = joydev->keymap[code - BTN_MISC]; | 132 | event.number = joydev->keymap[code - BTN_MISC]; |
101 | event.value = value; | 133 | event.value = value; |
102 | break; | 134 | break; |
103 | |||
104 | case EV_ABS: | ||
105 | event.type = JS_EVENT_AXIS; | ||
106 | event.number = joydev->absmap[code]; | ||
107 | event.value = joydev_correct(value, joydev->corr + event.number); | ||
108 | if (event.value == joydev->abs[event.number]) | ||
109 | return; | ||
110 | joydev->abs[event.number] = event.value; | ||
111 | break; | ||
112 | 135 | ||
113 | default: | 136 | case EV_ABS: |
137 | event.type = JS_EVENT_AXIS; | ||
138 | event.number = joydev->absmap[code]; | ||
139 | event.value = joydev_correct(value, | ||
140 | &joydev->corr[event.number]); | ||
141 | if (event.value == joydev->abs[event.number]) | ||
114 | return; | 142 | return; |
143 | joydev->abs[event.number] = event.value; | ||
144 | break; | ||
145 | |||
146 | default: | ||
147 | return; | ||
115 | } | 148 | } |
116 | 149 | ||
117 | event.time = jiffies_to_msecs(jiffies); | 150 | event.time = jiffies_to_msecs(jiffies); |
118 | 151 | ||
119 | list_for_each_entry(client, &joydev->client_list, node) { | 152 | rcu_read_lock(); |
120 | 153 | list_for_each_entry_rcu(client, &joydev->client_list, node) | |
121 | memcpy(client->buffer + client->head, &event, sizeof(struct js_event)); | 154 | joydev_pass_event(client, &event); |
122 | 155 | rcu_read_unlock(); | |
123 | if (client->startup == joydev->nabs + joydev->nkey) | ||
124 | if (client->tail == (client->head = (client->head + 1) & (JOYDEV_BUFFER_SIZE - 1))) | ||
125 | client->startup = 0; | ||
126 | |||
127 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
128 | } | ||
129 | 156 | ||
130 | wake_up_interruptible(&joydev->wait); | 157 | wake_up_interruptible(&joydev->wait); |
131 | } | 158 | } |
@@ -144,23 +171,83 @@ static void joydev_free(struct device *dev) | |||
144 | { | 171 | { |
145 | struct joydev *joydev = container_of(dev, struct joydev, dev); | 172 | struct joydev *joydev = container_of(dev, struct joydev, dev); |
146 | 173 | ||
147 | joydev_table[joydev->minor] = NULL; | ||
148 | kfree(joydev); | 174 | kfree(joydev); |
149 | } | 175 | } |
150 | 176 | ||
177 | static void joydev_attach_client(struct joydev *joydev, | ||
178 | struct joydev_client *client) | ||
179 | { | ||
180 | spin_lock(&joydev->client_lock); | ||
181 | list_add_tail_rcu(&client->node, &joydev->client_list); | ||
182 | spin_unlock(&joydev->client_lock); | ||
183 | synchronize_rcu(); | ||
184 | } | ||
185 | |||
186 | static void joydev_detach_client(struct joydev *joydev, | ||
187 | struct joydev_client *client) | ||
188 | { | ||
189 | spin_lock(&joydev->client_lock); | ||
190 | list_del_rcu(&client->node); | ||
191 | spin_unlock(&joydev->client_lock); | ||
192 | synchronize_rcu(); | ||
193 | } | ||
194 | |||
195 | static int joydev_open_device(struct joydev *joydev) | ||
196 | { | ||
197 | int retval; | ||
198 | |||
199 | retval = mutex_lock_interruptible(&joydev->mutex); | ||
200 | if (retval) | ||
201 | return retval; | ||
202 | |||
203 | if (!joydev->exist) | ||
204 | retval = -ENODEV; | ||
205 | else if (!joydev->open++) { | ||
206 | retval = input_open_device(&joydev->handle); | ||
207 | if (retval) | ||
208 | joydev->open--; | ||
209 | } | ||
210 | |||
211 | mutex_unlock(&joydev->mutex); | ||
212 | return retval; | ||
213 | } | ||
214 | |||
215 | static void joydev_close_device(struct joydev *joydev) | ||
216 | { | ||
217 | mutex_lock(&joydev->mutex); | ||
218 | |||
219 | if (joydev->exist && !--joydev->open) | ||
220 | input_close_device(&joydev->handle); | ||
221 | |||
222 | mutex_unlock(&joydev->mutex); | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * Wake up users waiting for IO so they can disconnect from | ||
227 | * dead device. | ||
228 | */ | ||
229 | static void joydev_hangup(struct joydev *joydev) | ||
230 | { | ||
231 | struct joydev_client *client; | ||
232 | |||
233 | spin_lock(&joydev->client_lock); | ||
234 | list_for_each_entry(client, &joydev->client_list, node) | ||
235 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
236 | spin_unlock(&joydev->client_lock); | ||
237 | |||
238 | wake_up_interruptible(&joydev->wait); | ||
239 | } | ||
240 | |||
151 | static int joydev_release(struct inode *inode, struct file *file) | 241 | static int joydev_release(struct inode *inode, struct file *file) |
152 | { | 242 | { |
153 | struct joydev_client *client = file->private_data; | 243 | struct joydev_client *client = file->private_data; |
154 | struct joydev *joydev = client->joydev; | 244 | struct joydev *joydev = client->joydev; |
155 | 245 | ||
156 | joydev_fasync(-1, file, 0); | 246 | joydev_fasync(-1, file, 0); |
157 | 247 | joydev_detach_client(joydev, client); | |
158 | list_del(&client->node); | ||
159 | kfree(client); | 248 | kfree(client); |
160 | 249 | ||
161 | if (!--joydev->open && joydev->exist) | 250 | joydev_close_device(joydev); |
162 | input_close_device(&joydev->handle); | ||
163 | |||
164 | put_device(&joydev->dev); | 251 | put_device(&joydev->dev); |
165 | 252 | ||
166 | return 0; | 253 | return 0; |
@@ -176,11 +263,16 @@ static int joydev_open(struct inode *inode, struct file *file) | |||
176 | if (i >= JOYDEV_MINORS) | 263 | if (i >= JOYDEV_MINORS) |
177 | return -ENODEV; | 264 | return -ENODEV; |
178 | 265 | ||
266 | error = mutex_lock_interruptible(&joydev_table_mutex); | ||
267 | if (error) | ||
268 | return error; | ||
179 | joydev = joydev_table[i]; | 269 | joydev = joydev_table[i]; |
180 | if (!joydev || !joydev->exist) | 270 | if (joydev) |
181 | return -ENODEV; | 271 | get_device(&joydev->dev); |
272 | mutex_unlock(&joydev_table_mutex); | ||
182 | 273 | ||
183 | get_device(&joydev->dev); | 274 | if (!joydev) |
275 | return -ENODEV; | ||
184 | 276 | ||
185 | client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); | 277 | client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); |
186 | if (!client) { | 278 | if (!client) { |
@@ -188,37 +280,129 @@ static int joydev_open(struct inode *inode, struct file *file) | |||
188 | goto err_put_joydev; | 280 | goto err_put_joydev; |
189 | } | 281 | } |
190 | 282 | ||
283 | spin_lock_init(&client->buffer_lock); | ||
191 | client->joydev = joydev; | 284 | client->joydev = joydev; |
192 | list_add_tail(&client->node, &joydev->client_list); | 285 | joydev_attach_client(joydev, client); |
193 | 286 | ||
194 | if (!joydev->open++ && joydev->exist) { | 287 | error = joydev_open_device(joydev); |
195 | error = input_open_device(&joydev->handle); | 288 | if (error) |
196 | if (error) | 289 | goto err_free_client; |
197 | goto err_free_client; | ||
198 | } | ||
199 | 290 | ||
200 | file->private_data = client; | 291 | file->private_data = client; |
201 | return 0; | 292 | return 0; |
202 | 293 | ||
203 | err_free_client: | 294 | err_free_client: |
204 | list_del(&client->node); | 295 | joydev_detach_client(joydev, client); |
205 | kfree(client); | 296 | kfree(client); |
206 | err_put_joydev: | 297 | err_put_joydev: |
207 | put_device(&joydev->dev); | 298 | put_device(&joydev->dev); |
208 | return error; | 299 | return error; |
209 | } | 300 | } |
210 | 301 | ||
211 | static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 302 | static int joydev_generate_startup_event(struct joydev_client *client, |
303 | struct input_dev *input, | ||
304 | struct js_event *event) | ||
212 | { | 305 | { |
213 | return -EINVAL; | 306 | struct joydev *joydev = client->joydev; |
307 | int have_event; | ||
308 | |||
309 | spin_lock_irq(&client->buffer_lock); | ||
310 | |||
311 | have_event = client->startup < joydev->nabs + joydev->nkey; | ||
312 | |||
313 | if (have_event) { | ||
314 | |||
315 | event->time = jiffies_to_msecs(jiffies); | ||
316 | if (client->startup < joydev->nkey) { | ||
317 | event->type = JS_EVENT_BUTTON | JS_EVENT_INIT; | ||
318 | event->number = client->startup; | ||
319 | event->value = !!test_bit(joydev->keypam[event->number], | ||
320 | input->key); | ||
321 | } else { | ||
322 | event->type = JS_EVENT_AXIS | JS_EVENT_INIT; | ||
323 | event->number = client->startup - joydev->nkey; | ||
324 | event->value = joydev->abs[event->number]; | ||
325 | } | ||
326 | client->startup++; | ||
327 | } | ||
328 | |||
329 | spin_unlock_irq(&client->buffer_lock); | ||
330 | |||
331 | return have_event; | ||
332 | } | ||
333 | |||
334 | static int joydev_fetch_next_event(struct joydev_client *client, | ||
335 | struct js_event *event) | ||
336 | { | ||
337 | int have_event; | ||
338 | |||
339 | spin_lock_irq(&client->buffer_lock); | ||
340 | |||
341 | have_event = client->head != client->tail; | ||
342 | if (have_event) { | ||
343 | *event = client->buffer[client->tail++]; | ||
344 | client->tail &= JOYDEV_BUFFER_SIZE - 1; | ||
345 | } | ||
346 | |||
347 | spin_unlock_irq(&client->buffer_lock); | ||
348 | |||
349 | return have_event; | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * Old joystick interface | ||
354 | */ | ||
355 | static ssize_t joydev_0x_read(struct joydev_client *client, | ||
356 | struct input_dev *input, | ||
357 | char __user *buf) | ||
358 | { | ||
359 | struct joydev *joydev = client->joydev; | ||
360 | struct JS_DATA_TYPE data; | ||
361 | int i; | ||
362 | |||
363 | spin_lock_irq(&input->event_lock); | ||
364 | |||
365 | /* | ||
366 | * Get device state | ||
367 | */ | ||
368 | for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++) | ||
369 | data.buttons |= | ||
370 | test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0; | ||
371 | data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x; | ||
372 | data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y; | ||
373 | |||
374 | /* | ||
375 | * Reset reader's event queue | ||
376 | */ | ||
377 | spin_lock(&client->buffer_lock); | ||
378 | client->startup = 0; | ||
379 | client->tail = client->head; | ||
380 | spin_unlock(&client->buffer_lock); | ||
381 | |||
382 | spin_unlock_irq(&input->event_lock); | ||
383 | |||
384 | if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE))) | ||
385 | return -EFAULT; | ||
386 | |||
387 | return sizeof(struct JS_DATA_TYPE); | ||
388 | } | ||
389 | |||
390 | static inline int joydev_data_pending(struct joydev_client *client) | ||
391 | { | ||
392 | struct joydev *joydev = client->joydev; | ||
393 | |||
394 | return client->startup < joydev->nabs + joydev->nkey || | ||
395 | client->head != client->tail; | ||
214 | } | 396 | } |
215 | 397 | ||
216 | static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 398 | static ssize_t joydev_read(struct file *file, char __user *buf, |
399 | size_t count, loff_t *ppos) | ||
217 | { | 400 | { |
218 | struct joydev_client *client = file->private_data; | 401 | struct joydev_client *client = file->private_data; |
219 | struct joydev *joydev = client->joydev; | 402 | struct joydev *joydev = client->joydev; |
220 | struct input_dev *input = joydev->handle.dev; | 403 | struct input_dev *input = joydev->handle.dev; |
221 | int retval = 0; | 404 | struct js_event event; |
405 | int retval; | ||
222 | 406 | ||
223 | if (!joydev->exist) | 407 | if (!joydev->exist) |
224 | return -ENODEV; | 408 | return -ENODEV; |
@@ -226,68 +410,35 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo | |||
226 | if (count < sizeof(struct js_event)) | 410 | if (count < sizeof(struct js_event)) |
227 | return -EINVAL; | 411 | return -EINVAL; |
228 | 412 | ||
229 | if (count == sizeof(struct JS_DATA_TYPE)) { | 413 | if (count == sizeof(struct JS_DATA_TYPE)) |
230 | 414 | return joydev_0x_read(client, input, buf); | |
231 | struct JS_DATA_TYPE data; | ||
232 | int i; | ||
233 | |||
234 | for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++) | ||
235 | data.buttons |= test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0; | ||
236 | data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x; | ||
237 | data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y; | ||
238 | |||
239 | if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE))) | ||
240 | return -EFAULT; | ||
241 | |||
242 | client->startup = 0; | ||
243 | client->tail = client->head; | ||
244 | 415 | ||
245 | return sizeof(struct JS_DATA_TYPE); | 416 | if (!joydev_data_pending(client) && (file->f_flags & O_NONBLOCK)) |
246 | } | ||
247 | |||
248 | if (client->startup == joydev->nabs + joydev->nkey && | ||
249 | client->head == client->tail && (file->f_flags & O_NONBLOCK)) | ||
250 | return -EAGAIN; | 417 | return -EAGAIN; |
251 | 418 | ||
252 | retval = wait_event_interruptible(joydev->wait, | 419 | retval = wait_event_interruptible(joydev->wait, |
253 | !joydev->exist || | 420 | !joydev->exist || joydev_data_pending(client)); |
254 | client->startup < joydev->nabs + joydev->nkey || | ||
255 | client->head != client->tail); | ||
256 | if (retval) | 421 | if (retval) |
257 | return retval; | 422 | return retval; |
258 | 423 | ||
259 | if (!joydev->exist) | 424 | if (!joydev->exist) |
260 | return -ENODEV; | 425 | return -ENODEV; |
261 | 426 | ||
262 | while (client->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) { | 427 | while (retval + sizeof(struct js_event) <= count && |
263 | 428 | joydev_generate_startup_event(client, input, &event)) { | |
264 | struct js_event event; | ||
265 | |||
266 | event.time = jiffies_to_msecs(jiffies); | ||
267 | |||
268 | if (client->startup < joydev->nkey) { | ||
269 | event.type = JS_EVENT_BUTTON | JS_EVENT_INIT; | ||
270 | event.number = client->startup; | ||
271 | event.value = !!test_bit(joydev->keypam[event.number], input->key); | ||
272 | } else { | ||
273 | event.type = JS_EVENT_AXIS | JS_EVENT_INIT; | ||
274 | event.number = client->startup - joydev->nkey; | ||
275 | event.value = joydev->abs[event.number]; | ||
276 | } | ||
277 | 429 | ||
278 | if (copy_to_user(buf + retval, &event, sizeof(struct js_event))) | 430 | if (copy_to_user(buf + retval, &event, sizeof(struct js_event))) |
279 | return -EFAULT; | 431 | return -EFAULT; |
280 | 432 | ||
281 | client->startup++; | ||
282 | retval += sizeof(struct js_event); | 433 | retval += sizeof(struct js_event); |
283 | } | 434 | } |
284 | 435 | ||
285 | while (client->head != client->tail && retval + sizeof(struct js_event) <= count) { | 436 | while (retval + sizeof(struct js_event) <= count && |
437 | joydev_fetch_next_event(client, &event)) { | ||
286 | 438 | ||
287 | if (copy_to_user(buf + retval, client->buffer + client->tail, sizeof(struct js_event))) | 439 | if (copy_to_user(buf + retval, &event, sizeof(struct js_event))) |
288 | return -EFAULT; | 440 | return -EFAULT; |
289 | 441 | ||
290 | client->tail = (client->tail + 1) & (JOYDEV_BUFFER_SIZE - 1); | ||
291 | retval += sizeof(struct js_event); | 442 | retval += sizeof(struct js_event); |
292 | } | 443 | } |
293 | 444 | ||
@@ -301,126 +452,144 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) | |||
301 | struct joydev *joydev = client->joydev; | 452 | struct joydev *joydev = client->joydev; |
302 | 453 | ||
303 | poll_wait(file, &joydev->wait, wait); | 454 | poll_wait(file, &joydev->wait, wait); |
304 | return ((client->head != client->tail || client->startup < joydev->nabs + joydev->nkey) ? | 455 | return (joydev_data_pending(client) ? (POLLIN | POLLRDNORM) : 0) | |
305 | (POLLIN | POLLRDNORM) : 0) | (joydev->exist ? 0 : (POLLHUP | POLLERR)); | 456 | (joydev->exist ? 0 : (POLLHUP | POLLERR)); |
306 | } | 457 | } |
307 | 458 | ||
308 | static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp) | 459 | static int joydev_ioctl_common(struct joydev *joydev, |
460 | unsigned int cmd, void __user *argp) | ||
309 | { | 461 | { |
310 | struct input_dev *dev = joydev->handle.dev; | 462 | struct input_dev *dev = joydev->handle.dev; |
311 | int i, j; | 463 | int i, j; |
312 | 464 | ||
313 | switch (cmd) { | 465 | switch (cmd) { |
314 | 466 | ||
315 | case JS_SET_CAL: | 467 | case JS_SET_CAL: |
316 | return copy_from_user(&joydev->glue.JS_CORR, argp, | 468 | return copy_from_user(&joydev->glue.JS_CORR, argp, |
317 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; | 469 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
318 | 470 | ||
319 | case JS_GET_CAL: | 471 | case JS_GET_CAL: |
320 | return copy_to_user(argp, &joydev->glue.JS_CORR, | 472 | return copy_to_user(argp, &joydev->glue.JS_CORR, |
321 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; | 473 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
322 | 474 | ||
323 | case JS_SET_TIMEOUT: | 475 | case JS_SET_TIMEOUT: |
324 | return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); | 476 | return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
325 | 477 | ||
326 | case JS_GET_TIMEOUT: | 478 | case JS_GET_TIMEOUT: |
327 | return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); | 479 | return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
328 | 480 | ||
329 | case JSIOCGVERSION: | 481 | case JSIOCGVERSION: |
330 | return put_user(JS_VERSION, (__u32 __user *) argp); | 482 | return put_user(JS_VERSION, (__u32 __user *) argp); |
331 | 483 | ||
332 | case JSIOCGAXES: | 484 | case JSIOCGAXES: |
333 | return put_user(joydev->nabs, (__u8 __user *) argp); | 485 | return put_user(joydev->nabs, (__u8 __user *) argp); |
334 | 486 | ||
335 | case JSIOCGBUTTONS: | 487 | case JSIOCGBUTTONS: |
336 | return put_user(joydev->nkey, (__u8 __user *) argp); | 488 | return put_user(joydev->nkey, (__u8 __user *) argp); |
337 | 489 | ||
338 | case JSIOCSCORR: | 490 | case JSIOCSCORR: |
339 | if (copy_from_user(joydev->corr, argp, | 491 | if (copy_from_user(joydev->corr, argp, |
340 | sizeof(joydev->corr[0]) * joydev->nabs)) | 492 | sizeof(joydev->corr[0]) * joydev->nabs)) |
341 | return -EFAULT; | 493 | return -EFAULT; |
342 | for (i = 0; i < joydev->nabs; i++) { | ||
343 | j = joydev->abspam[i]; | ||
344 | joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); | ||
345 | } | ||
346 | return 0; | ||
347 | 494 | ||
348 | case JSIOCGCORR: | 495 | for (i = 0; i < joydev->nabs; i++) { |
349 | return copy_to_user(argp, joydev->corr, | 496 | j = joydev->abspam[i]; |
350 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; | 497 | joydev->abs[i] = joydev_correct(dev->abs[j], |
498 | &joydev->corr[i]); | ||
499 | } | ||
500 | return 0; | ||
351 | 501 | ||
352 | case JSIOCSAXMAP: | 502 | case JSIOCGCORR: |
353 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) | 503 | return copy_to_user(argp, joydev->corr, |
354 | return -EFAULT; | 504 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; |
355 | for (i = 0; i < joydev->nabs; i++) { | 505 | |
356 | if (joydev->abspam[i] > ABS_MAX) | 506 | case JSIOCSAXMAP: |
357 | return -EINVAL; | 507 | if (copy_from_user(joydev->abspam, argp, |
358 | joydev->absmap[joydev->abspam[i]] = i; | 508 | sizeof(__u8) * (ABS_MAX + 1))) |
359 | } | 509 | return -EFAULT; |
360 | return 0; | 510 | |
361 | 511 | for (i = 0; i < joydev->nabs; i++) { | |
362 | case JSIOCGAXMAP: | 512 | if (joydev->abspam[i] > ABS_MAX) |
363 | return copy_to_user(argp, joydev->abspam, | 513 | return -EINVAL; |
364 | sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; | 514 | joydev->absmap[joydev->abspam[i]] = i; |
365 | 515 | } | |
366 | case JSIOCSBTNMAP: | 516 | return 0; |
367 | if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) | 517 | |
518 | case JSIOCGAXMAP: | ||
519 | return copy_to_user(argp, joydev->abspam, | ||
520 | sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; | ||
521 | |||
522 | case JSIOCSBTNMAP: | ||
523 | if (copy_from_user(joydev->keypam, argp, | ||
524 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) | ||
525 | return -EFAULT; | ||
526 | |||
527 | for (i = 0; i < joydev->nkey; i++) { | ||
528 | if (joydev->keypam[i] > KEY_MAX || | ||
529 | joydev->keypam[i] < BTN_MISC) | ||
530 | return -EINVAL; | ||
531 | joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; | ||
532 | } | ||
533 | |||
534 | return 0; | ||
535 | |||
536 | case JSIOCGBTNMAP: | ||
537 | return copy_to_user(argp, joydev->keypam, | ||
538 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; | ||
539 | |||
540 | default: | ||
541 | if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { | ||
542 | int len; | ||
543 | if (!dev->name) | ||
544 | return 0; | ||
545 | len = strlen(dev->name) + 1; | ||
546 | if (len > _IOC_SIZE(cmd)) | ||
547 | len = _IOC_SIZE(cmd); | ||
548 | if (copy_to_user(argp, dev->name, len)) | ||
368 | return -EFAULT; | 549 | return -EFAULT; |
369 | for (i = 0; i < joydev->nkey; i++) { | 550 | return len; |
370 | if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) | 551 | } |
371 | return -EINVAL; | ||
372 | joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; | ||
373 | } | ||
374 | return 0; | ||
375 | |||
376 | case JSIOCGBTNMAP: | ||
377 | return copy_to_user(argp, joydev->keypam, | ||
378 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; | ||
379 | |||
380 | default: | ||
381 | if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) { | ||
382 | int len; | ||
383 | if (!dev->name) | ||
384 | return 0; | ||
385 | len = strlen(dev->name) + 1; | ||
386 | if (len > _IOC_SIZE(cmd)) | ||
387 | len = _IOC_SIZE(cmd); | ||
388 | if (copy_to_user(argp, dev->name, len)) | ||
389 | return -EFAULT; | ||
390 | return len; | ||
391 | } | ||
392 | } | 552 | } |
393 | return -EINVAL; | 553 | return -EINVAL; |
394 | } | 554 | } |
395 | 555 | ||
396 | #ifdef CONFIG_COMPAT | 556 | #ifdef CONFIG_COMPAT |
397 | static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 557 | static long joydev_compat_ioctl(struct file *file, |
558 | unsigned int cmd, unsigned long arg) | ||
398 | { | 559 | { |
399 | struct joydev_client *client = file->private_data; | 560 | struct joydev_client *client = file->private_data; |
400 | struct joydev *joydev = client->joydev; | 561 | struct joydev *joydev = client->joydev; |
401 | void __user *argp = (void __user *)arg; | 562 | void __user *argp = (void __user *)arg; |
402 | s32 tmp32; | 563 | s32 tmp32; |
403 | struct JS_DATA_SAVE_TYPE_32 ds32; | 564 | struct JS_DATA_SAVE_TYPE_32 ds32; |
404 | int err; | 565 | int retval; |
405 | 566 | ||
406 | if (!joydev->exist) | 567 | retval = mutex_lock_interruptible(&joydev->mutex); |
407 | return -ENODEV; | 568 | if (retval) |
569 | return retval; | ||
570 | |||
571 | if (!joydev->exist) { | ||
572 | retval = -ENODEV; | ||
573 | goto out; | ||
574 | } | ||
575 | |||
576 | switch (cmd) { | ||
408 | 577 | ||
409 | switch(cmd) { | ||
410 | case JS_SET_TIMELIMIT: | 578 | case JS_SET_TIMELIMIT: |
411 | err = get_user(tmp32, (s32 __user *) arg); | 579 | retval = get_user(tmp32, (s32 __user *) arg); |
412 | if (err == 0) | 580 | if (retval == 0) |
413 | joydev->glue.JS_TIMELIMIT = tmp32; | 581 | joydev->glue.JS_TIMELIMIT = tmp32; |
414 | break; | 582 | break; |
583 | |||
415 | case JS_GET_TIMELIMIT: | 584 | case JS_GET_TIMELIMIT: |
416 | tmp32 = joydev->glue.JS_TIMELIMIT; | 585 | tmp32 = joydev->glue.JS_TIMELIMIT; |
417 | err = put_user(tmp32, (s32 __user *) arg); | 586 | retval = put_user(tmp32, (s32 __user *) arg); |
418 | break; | 587 | break; |
419 | 588 | ||
420 | case JS_SET_ALL: | 589 | case JS_SET_ALL: |
421 | err = copy_from_user(&ds32, argp, | 590 | retval = copy_from_user(&ds32, argp, |
422 | sizeof(ds32)) ? -EFAULT : 0; | 591 | sizeof(ds32)) ? -EFAULT : 0; |
423 | if (err == 0) { | 592 | if (retval == 0) { |
424 | joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT; | 593 | joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT; |
425 | joydev->glue.BUSY = ds32.BUSY; | 594 | joydev->glue.BUSY = ds32.BUSY; |
426 | joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME; | 595 | joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME; |
@@ -438,55 +607,119 @@ static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo | |||
438 | ds32.JS_SAVE = joydev->glue.JS_SAVE; | 607 | ds32.JS_SAVE = joydev->glue.JS_SAVE; |
439 | ds32.JS_CORR = joydev->glue.JS_CORR; | 608 | ds32.JS_CORR = joydev->glue.JS_CORR; |
440 | 609 | ||
441 | err = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0; | 610 | retval = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0; |
442 | break; | 611 | break; |
443 | 612 | ||
444 | default: | 613 | default: |
445 | err = joydev_ioctl_common(joydev, cmd, argp); | 614 | retval = joydev_ioctl_common(joydev, cmd, argp); |
615 | break; | ||
446 | } | 616 | } |
447 | return err; | 617 | |
618 | out: | ||
619 | mutex_unlock(&joydev->mutex); | ||
620 | return retval; | ||
448 | } | 621 | } |
449 | #endif /* CONFIG_COMPAT */ | 622 | #endif /* CONFIG_COMPAT */ |
450 | 623 | ||
451 | static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 624 | static long joydev_ioctl(struct file *file, |
625 | unsigned int cmd, unsigned long arg) | ||
452 | { | 626 | { |
453 | struct joydev_client *client = file->private_data; | 627 | struct joydev_client *client = file->private_data; |
454 | struct joydev *joydev = client->joydev; | 628 | struct joydev *joydev = client->joydev; |
455 | void __user *argp = (void __user *)arg; | 629 | void __user *argp = (void __user *)arg; |
630 | int retval; | ||
456 | 631 | ||
457 | if (!joydev->exist) | 632 | retval = mutex_lock_interruptible(&joydev->mutex); |
458 | return -ENODEV; | 633 | if (retval) |
634 | return retval; | ||
635 | |||
636 | if (!joydev->exist) { | ||
637 | retval = -ENODEV; | ||
638 | goto out; | ||
639 | } | ||
640 | |||
641 | switch (cmd) { | ||
642 | |||
643 | case JS_SET_TIMELIMIT: | ||
644 | retval = get_user(joydev->glue.JS_TIMELIMIT, | ||
645 | (long __user *) arg); | ||
646 | break; | ||
647 | |||
648 | case JS_GET_TIMELIMIT: | ||
649 | retval = put_user(joydev->glue.JS_TIMELIMIT, | ||
650 | (long __user *) arg); | ||
651 | break; | ||
652 | |||
653 | case JS_SET_ALL: | ||
654 | retval = copy_from_user(&joydev->glue, argp, | ||
655 | sizeof(joydev->glue)) ? -EFAULT: 0; | ||
656 | break; | ||
657 | |||
658 | case JS_GET_ALL: | ||
659 | retval = copy_to_user(argp, &joydev->glue, | ||
660 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
661 | break; | ||
459 | 662 | ||
460 | switch(cmd) { | 663 | default: |
461 | case JS_SET_TIMELIMIT: | 664 | retval = joydev_ioctl_common(joydev, cmd, argp); |
462 | return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | 665 | break; |
463 | case JS_GET_TIMELIMIT: | ||
464 | return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
465 | case JS_SET_ALL: | ||
466 | return copy_from_user(&joydev->glue, argp, | ||
467 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
468 | case JS_GET_ALL: | ||
469 | return copy_to_user(argp, &joydev->glue, | ||
470 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
471 | default: | ||
472 | return joydev_ioctl_common(joydev, cmd, argp); | ||
473 | } | 666 | } |
667 | out: | ||
668 | mutex_unlock(&joydev->mutex); | ||
669 | return retval; | ||
474 | } | 670 | } |
475 | 671 | ||
476 | static const struct file_operations joydev_fops = { | 672 | static const struct file_operations joydev_fops = { |
477 | .owner = THIS_MODULE, | 673 | .owner = THIS_MODULE, |
478 | .read = joydev_read, | 674 | .read = joydev_read, |
479 | .write = joydev_write, | 675 | .poll = joydev_poll, |
480 | .poll = joydev_poll, | 676 | .open = joydev_open, |
481 | .open = joydev_open, | 677 | .release = joydev_release, |
482 | .release = joydev_release, | 678 | .unlocked_ioctl = joydev_ioctl, |
483 | .ioctl = joydev_ioctl, | ||
484 | #ifdef CONFIG_COMPAT | 679 | #ifdef CONFIG_COMPAT |
485 | .compat_ioctl = joydev_compat_ioctl, | 680 | .compat_ioctl = joydev_compat_ioctl, |
486 | #endif | 681 | #endif |
487 | .fasync = joydev_fasync, | 682 | .fasync = joydev_fasync, |
488 | }; | 683 | }; |
489 | 684 | ||
685 | static int joydev_install_chrdev(struct joydev *joydev) | ||
686 | { | ||
687 | joydev_table[joydev->minor] = joydev; | ||
688 | return 0; | ||
689 | } | ||
690 | |||
691 | static void joydev_remove_chrdev(struct joydev *joydev) | ||
692 | { | ||
693 | mutex_lock(&joydev_table_mutex); | ||
694 | joydev_table[joydev->minor] = NULL; | ||
695 | mutex_unlock(&joydev_table_mutex); | ||
696 | } | ||
697 | |||
698 | /* | ||
699 | * Mark device non-existant. This disables writes, ioctls and | ||
700 | * prevents new users from opening the device. Already posted | ||
701 | * blocking reads will stay, however new ones will fail. | ||
702 | */ | ||
703 | static void joydev_mark_dead(struct joydev *joydev) | ||
704 | { | ||
705 | mutex_lock(&joydev->mutex); | ||
706 | joydev->exist = 0; | ||
707 | mutex_unlock(&joydev->mutex); | ||
708 | } | ||
709 | |||
710 | static void joydev_cleanup(struct joydev *joydev) | ||
711 | { | ||
712 | struct input_handle *handle = &joydev->handle; | ||
713 | |||
714 | joydev_mark_dead(joydev); | ||
715 | joydev_hangup(joydev); | ||
716 | joydev_remove_chrdev(joydev); | ||
717 | |||
718 | /* joydev is marked dead so noone else accesses joydev->open */ | ||
719 | if (joydev->open) | ||
720 | input_close_device(handle); | ||
721 | } | ||
722 | |||
490 | static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | 723 | static int joydev_connect(struct input_handler *handler, struct input_dev *dev, |
491 | const struct input_device_id *id) | 724 | const struct input_device_id *id) |
492 | { | 725 | { |
@@ -494,7 +727,10 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
494 | int i, j, t, minor; | 727 | int i, j, t, minor; |
495 | int error; | 728 | int error; |
496 | 729 | ||
497 | for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); | 730 | for (minor = 0; minor < JOYDEV_MINORS; minor++) |
731 | if (!joydev_table[minor]) | ||
732 | break; | ||
733 | |||
498 | if (minor == JOYDEV_MINORS) { | 734 | if (minor == JOYDEV_MINORS) { |
499 | printk(KERN_ERR "joydev: no more free joydev devices\n"); | 735 | printk(KERN_ERR "joydev: no more free joydev devices\n"); |
500 | return -ENFILE; | 736 | return -ENFILE; |
@@ -505,15 +741,19 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
505 | return -ENOMEM; | 741 | return -ENOMEM; |
506 | 742 | ||
507 | INIT_LIST_HEAD(&joydev->client_list); | 743 | INIT_LIST_HEAD(&joydev->client_list); |
744 | spin_lock_init(&joydev->client_lock); | ||
745 | mutex_init(&joydev->mutex); | ||
508 | init_waitqueue_head(&joydev->wait); | 746 | init_waitqueue_head(&joydev->wait); |
509 | 747 | ||
748 | snprintf(joydev->name, sizeof(joydev->name), "js%d", minor); | ||
749 | joydev->exist = 1; | ||
510 | joydev->minor = minor; | 750 | joydev->minor = minor; |
751 | |||
511 | joydev->exist = 1; | 752 | joydev->exist = 1; |
512 | joydev->handle.dev = dev; | 753 | joydev->handle.dev = dev; |
513 | joydev->handle.name = joydev->name; | 754 | joydev->handle.name = joydev->name; |
514 | joydev->handle.handler = handler; | 755 | joydev->handle.handler = handler; |
515 | joydev->handle.private = joydev; | 756 | joydev->handle.private = joydev; |
516 | snprintf(joydev->name, sizeof(joydev->name), "js%d", minor); | ||
517 | 757 | ||
518 | for (i = 0; i < ABS_MAX + 1; i++) | 758 | for (i = 0; i < ABS_MAX + 1; i++) |
519 | if (test_bit(i, dev->absbit)) { | 759 | if (test_bit(i, dev->absbit)) { |
@@ -545,67 +785,65 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
545 | } | 785 | } |
546 | joydev->corr[i].type = JS_CORR_BROKEN; | 786 | joydev->corr[i].type = JS_CORR_BROKEN; |
547 | joydev->corr[i].prec = dev->absfuzz[j]; | 787 | joydev->corr[i].prec = dev->absfuzz[j]; |
548 | joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j]; | 788 | joydev->corr[i].coef[0] = |
549 | joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j]; | 789 | (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j]; |
550 | if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]))) | 790 | joydev->corr[i].coef[1] = |
551 | continue; | 791 | (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j]; |
552 | joydev->corr[i].coef[2] = (1 << 29) / t; | 792 | |
553 | joydev->corr[i].coef[3] = (1 << 29) / t; | 793 | t = (dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]; |
554 | 794 | if (t) { | |
555 | joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); | 795 | joydev->corr[i].coef[2] = (1 << 29) / t; |
796 | joydev->corr[i].coef[3] = (1 << 29) / t; | ||
797 | |||
798 | joydev->abs[i] = joydev_correct(dev->abs[j], | ||
799 | joydev->corr + i); | ||
800 | } | ||
556 | } | 801 | } |
557 | 802 | ||
558 | snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id), | 803 | strlcpy(joydev->dev.bus_id, joydev->name, sizeof(joydev->dev.bus_id)); |
559 | "js%d", minor); | 804 | joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); |
560 | joydev->dev.class = &input_class; | 805 | joydev->dev.class = &input_class; |
561 | joydev->dev.parent = &dev->dev; | 806 | joydev->dev.parent = &dev->dev; |
562 | joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); | ||
563 | joydev->dev.release = joydev_free; | 807 | joydev->dev.release = joydev_free; |
564 | device_initialize(&joydev->dev); | 808 | device_initialize(&joydev->dev); |
565 | 809 | ||
566 | joydev_table[minor] = joydev; | 810 | error = input_register_handle(&joydev->handle); |
567 | |||
568 | error = device_add(&joydev->dev); | ||
569 | if (error) | 811 | if (error) |
570 | goto err_free_joydev; | 812 | goto err_free_joydev; |
571 | 813 | ||
572 | error = input_register_handle(&joydev->handle); | 814 | error = joydev_install_chrdev(joydev); |
573 | if (error) | 815 | if (error) |
574 | goto err_delete_joydev; | 816 | goto err_unregister_handle; |
817 | |||
818 | error = device_add(&joydev->dev); | ||
819 | if (error) | ||
820 | goto err_cleanup_joydev; | ||
575 | 821 | ||
576 | return 0; | 822 | return 0; |
577 | 823 | ||
578 | err_delete_joydev: | 824 | err_cleanup_joydev: |
579 | device_del(&joydev->dev); | 825 | joydev_cleanup(joydev); |
826 | err_unregister_handle: | ||
827 | input_unregister_handle(&joydev->handle); | ||
580 | err_free_joydev: | 828 | err_free_joydev: |
581 | put_device(&joydev->dev); | 829 | put_device(&joydev->dev); |
582 | return error; | 830 | return error; |
583 | } | 831 | } |
584 | 832 | ||
585 | |||
586 | static void joydev_disconnect(struct input_handle *handle) | 833 | static void joydev_disconnect(struct input_handle *handle) |
587 | { | 834 | { |
588 | struct joydev *joydev = handle->private; | 835 | struct joydev *joydev = handle->private; |
589 | struct joydev_client *client; | ||
590 | 836 | ||
591 | input_unregister_handle(handle); | ||
592 | device_del(&joydev->dev); | 837 | device_del(&joydev->dev); |
593 | 838 | joydev_cleanup(joydev); | |
594 | joydev->exist = 0; | 839 | input_unregister_handle(handle); |
595 | |||
596 | if (joydev->open) { | ||
597 | input_close_device(handle); | ||
598 | list_for_each_entry(client, &joydev->client_list, node) | ||
599 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
600 | wake_up_interruptible(&joydev->wait); | ||
601 | } | ||
602 | |||
603 | put_device(&joydev->dev); | 840 | put_device(&joydev->dev); |
604 | } | 841 | } |
605 | 842 | ||
606 | static const struct input_device_id joydev_blacklist[] = { | 843 | static const struct input_device_id joydev_blacklist[] = { |
607 | { | 844 | { |
608 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, | 845 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
846 | INPUT_DEVICE_ID_MATCH_KEYBIT, | ||
609 | .evbit = { BIT(EV_KEY) }, | 847 | .evbit = { BIT(EV_KEY) }, |
610 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, | 848 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, |
611 | }, /* Avoid itouchpads, touchscreens and tablets */ | 849 | }, /* Avoid itouchpads, touchscreens and tablets */ |
@@ -614,17 +852,20 @@ static const struct input_device_id joydev_blacklist[] = { | |||
614 | 852 | ||
615 | static const struct input_device_id joydev_ids[] = { | 853 | static const struct input_device_id joydev_ids[] = { |
616 | { | 854 | { |
617 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | 855 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
856 | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
618 | .evbit = { BIT(EV_ABS) }, | 857 | .evbit = { BIT(EV_ABS) }, |
619 | .absbit = { BIT(ABS_X) }, | 858 | .absbit = { BIT(ABS_X) }, |
620 | }, | 859 | }, |
621 | { | 860 | { |
622 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | 861 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
862 | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
623 | .evbit = { BIT(EV_ABS) }, | 863 | .evbit = { BIT(EV_ABS) }, |
624 | .absbit = { BIT(ABS_WHEEL) }, | 864 | .absbit = { BIT(ABS_WHEEL) }, |
625 | }, | 865 | }, |
626 | { | 866 | { |
627 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | 867 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
868 | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
628 | .evbit = { BIT(EV_ABS) }, | 869 | .evbit = { BIT(EV_ABS) }, |
629 | .absbit = { BIT(ABS_THROTTLE) }, | 870 | .absbit = { BIT(ABS_THROTTLE) }, |
630 | }, | 871 | }, |
@@ -634,14 +875,14 @@ static const struct input_device_id joydev_ids[] = { | |||
634 | MODULE_DEVICE_TABLE(input, joydev_ids); | 875 | MODULE_DEVICE_TABLE(input, joydev_ids); |
635 | 876 | ||
636 | static struct input_handler joydev_handler = { | 877 | static struct input_handler joydev_handler = { |
637 | .event = joydev_event, | 878 | .event = joydev_event, |
638 | .connect = joydev_connect, | 879 | .connect = joydev_connect, |
639 | .disconnect = joydev_disconnect, | 880 | .disconnect = joydev_disconnect, |
640 | .fops = &joydev_fops, | 881 | .fops = &joydev_fops, |
641 | .minor = JOYDEV_MINOR_BASE, | 882 | .minor = JOYDEV_MINOR_BASE, |
642 | .name = "joydev", | 883 | .name = "joydev", |
643 | .id_table = joydev_ids, | 884 | .id_table = joydev_ids, |
644 | .blacklist = joydev_blacklist, | 885 | .blacklist = joydev_blacklist, |
645 | }; | 886 | }; |
646 | 887 | ||
647 | static int __init joydev_init(void) | 888 | static int __init joydev_init(void) |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 28080395899c..623629a69b03 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -223,12 +223,16 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
223 | struct input_dev *dev = xpad->dev; | 223 | struct input_dev *dev = xpad->dev; |
224 | 224 | ||
225 | /* left stick */ | 225 | /* left stick */ |
226 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); | 226 | input_report_abs(dev, ABS_X, |
227 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); | 227 | (__s16) le16_to_cpup((__le16 *)(data + 12))); |
228 | input_report_abs(dev, ABS_Y, | ||
229 | (__s16) le16_to_cpup((__le16 *)(data + 14))); | ||
228 | 230 | ||
229 | /* right stick */ | 231 | /* right stick */ |
230 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); | 232 | input_report_abs(dev, ABS_RX, |
231 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); | 233 | (__s16) le16_to_cpup((__le16 *)(data + 16))); |
234 | input_report_abs(dev, ABS_RY, | ||
235 | (__s16) le16_to_cpup((__le16 *)(data + 18))); | ||
232 | 236 | ||
233 | /* triggers left/right */ | 237 | /* triggers left/right */ |
234 | input_report_abs(dev, ABS_Z, data[10]); | 238 | input_report_abs(dev, ABS_Z, data[10]); |
@@ -236,8 +240,10 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
236 | 240 | ||
237 | /* digital pad */ | 241 | /* digital pad */ |
238 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { | 242 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { |
239 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); | 243 | input_report_abs(dev, ABS_HAT0X, |
240 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); | 244 | !!(data[2] & 0x08) - !!(data[2] & 0x04)); |
245 | input_report_abs(dev, ABS_HAT0Y, | ||
246 | !!(data[2] & 0x02) - !!(data[2] & 0x01)); | ||
241 | } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { | 247 | } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { |
242 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); | 248 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); |
243 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); | 249 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); |
@@ -274,14 +280,17 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
274 | * http://www.free60.org/wiki/Gamepad | 280 | * http://www.free60.org/wiki/Gamepad |
275 | */ | 281 | */ |
276 | 282 | ||
277 | static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) | 283 | static void xpad360_process_packet(struct usb_xpad *xpad, |
284 | u16 cmd, unsigned char *data) | ||
278 | { | 285 | { |
279 | struct input_dev *dev = xpad->dev; | 286 | struct input_dev *dev = xpad->dev; |
280 | 287 | ||
281 | /* digital pad */ | 288 | /* digital pad */ |
282 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { | 289 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { |
283 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); | 290 | input_report_abs(dev, ABS_HAT0X, |
284 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); | 291 | !!(data[2] & 0x08) - !!(data[2] & 0x04)); |
292 | input_report_abs(dev, ABS_HAT0Y, | ||
293 | !!(data[2] & 0x02) - !!(data[2] & 0x01)); | ||
285 | } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) { | 294 | } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) { |
286 | /* dpad as buttons (right, left, down, up) */ | 295 | /* dpad as buttons (right, left, down, up) */ |
287 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); | 296 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); |
@@ -308,12 +317,16 @@ static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char | |||
308 | input_report_key(dev, BTN_MODE, data[3] & 0x04); | 317 | input_report_key(dev, BTN_MODE, data[3] & 0x04); |
309 | 318 | ||
310 | /* left stick */ | 319 | /* left stick */ |
311 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[7] << 8) | (__s16)data[6])); | 320 | input_report_abs(dev, ABS_X, |
312 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[9] << 8) | (__s16)data[8])); | 321 | (__s16) le16_to_cpup((__le16 *)(data + 6))); |
322 | input_report_abs(dev, ABS_Y, | ||
323 | (__s16) le16_to_cpup((__le16 *)(data + 8))); | ||
313 | 324 | ||
314 | /* right stick */ | 325 | /* right stick */ |
315 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[11] << 8) | (__s16)data[10])); | 326 | input_report_abs(dev, ABS_RX, |
316 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[13] << 8) | (__s16)data[12])); | 327 | (__s16) le16_to_cpup((__le16 *)(data + 10))); |
328 | input_report_abs(dev, ABS_RY, | ||
329 | (__s16) le16_to_cpup((__le16 *)(data + 12))); | ||
317 | 330 | ||
318 | /* triggers left/right */ | 331 | /* triggers left/right */ |
319 | input_report_abs(dev, ABS_Z, data[4]); | 332 | input_report_abs(dev, ABS_Z, data[4]); |
@@ -335,10 +348,12 @@ static void xpad_irq_in(struct urb *urb) | |||
335 | case -ENOENT: | 348 | case -ENOENT: |
336 | case -ESHUTDOWN: | 349 | case -ESHUTDOWN: |
337 | /* this urb is terminated, clean up */ | 350 | /* this urb is terminated, clean up */ |
338 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 351 | dbg("%s - urb shutting down with status: %d", |
352 | __FUNCTION__, urb->status); | ||
339 | return; | 353 | return; |
340 | default: | 354 | default: |
341 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 355 | dbg("%s - nonzero urb status received: %d", |
356 | __FUNCTION__, urb->status); | ||
342 | goto exit; | 357 | goto exit; |
343 | } | 358 | } |
344 | 359 | ||
@@ -367,10 +382,12 @@ static void xpad_irq_out(struct urb *urb) | |||
367 | case -ENOENT: | 382 | case -ENOENT: |
368 | case -ESHUTDOWN: | 383 | case -ESHUTDOWN: |
369 | /* this urb is terminated, clean up */ | 384 | /* this urb is terminated, clean up */ |
370 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 385 | dbg("%s - urb shutting down with status: %d", |
386 | __FUNCTION__, urb->status); | ||
371 | return; | 387 | return; |
372 | default: | 388 | default: |
373 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 389 | dbg("%s - nonzero urb status received: %d", |
390 | __FUNCTION__, urb->status); | ||
374 | goto exit; | 391 | goto exit; |
375 | } | 392 | } |
376 | 393 | ||
@@ -378,7 +395,7 @@ exit: | |||
378 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 395 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
379 | if (retval) | 396 | if (retval) |
380 | err("%s - usb_submit_urb failed with result %d", | 397 | err("%s - usb_submit_urb failed with result %d", |
381 | __FUNCTION__, retval); | 398 | __FUNCTION__, retval); |
382 | } | 399 | } |
383 | 400 | ||
384 | static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) | 401 | static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) |
@@ -595,7 +612,7 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) | |||
595 | 612 | ||
596 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) | 613 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) |
597 | { | 614 | { |
598 | struct usb_device *udev = interface_to_usbdev (intf); | 615 | struct usb_device *udev = interface_to_usbdev(intf); |
599 | struct usb_xpad *xpad; | 616 | struct usb_xpad *xpad; |
600 | struct input_dev *input_dev; | 617 | struct input_dev *input_dev; |
601 | struct usb_endpoint_descriptor *ep_irq_in; | 618 | struct usb_endpoint_descriptor *ep_irq_in; |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index c97d5eb0075d..2316a018fae6 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -208,6 +208,27 @@ config KEYBOARD_HIL | |||
208 | This driver implements support for HIL-keyboards attached | 208 | This driver implements support for HIL-keyboards attached |
209 | to your machine, so normally you should say Y here. | 209 | to your machine, so normally you should say Y here. |
210 | 210 | ||
211 | config KEYBOARD_HP6XX | ||
212 | tristate "HP Jornada 6XX Keyboard support" | ||
213 | depends on SH_HP6XX | ||
214 | select INPUT_POLLDEV | ||
215 | help | ||
216 | This adds support for the onboard keyboard found on | ||
217 | HP Jornada 620/660/680/690. | ||
218 | |||
219 | To compile this driver as a module, choose M here: the | ||
220 | module will be called jornada680_kbd. | ||
221 | |||
222 | config KEYBOARD_HP7XX | ||
223 | tristate "HP Jornada 7XX Keyboard Driver" | ||
224 | depends on SA1100_JORNADA720_SSP && SA1100_SSP | ||
225 | help | ||
226 | Say Y here to add support for the HP Jornada 7xx (710/720/728) | ||
227 | onboard keyboard. | ||
228 | |||
229 | To compile this driver as a module, choose M here: the | ||
230 | module will be called jornada720_kbd. | ||
231 | |||
211 | config KEYBOARD_OMAP | 232 | config KEYBOARD_OMAP |
212 | tristate "TI OMAP keypad support" | 233 | tristate "TI OMAP keypad support" |
213 | depends on (ARCH_OMAP1 || ARCH_OMAP2) | 234 | depends on (ARCH_OMAP1 || ARCH_OMAP2) |
@@ -253,4 +274,23 @@ config KEYBOARD_GPIO | |||
253 | To compile this driver as a module, choose M here: the | 274 | To compile this driver as a module, choose M here: the |
254 | module will be called gpio-keys. | 275 | module will be called gpio-keys. |
255 | 276 | ||
277 | config KEYBOARD_MAPLE | ||
278 | tristate "Maple bus keyboard" | ||
279 | depends on SH_DREAMCAST && MAPLE | ||
280 | help | ||
281 | Say Y here if you have a Dreamcast console running Linux and have | ||
282 | a keyboard attached to its Maple bus. | ||
283 | |||
284 | To compile this driver as a module, choose M here: the | ||
285 | module will be called maple_keyb. | ||
286 | |||
287 | config KEYBOARD_BFIN | ||
288 | tristate "Blackfin BF54x keypad support" | ||
289 | depends on BF54x | ||
290 | help | ||
291 | Say Y here if you want to use the BF54x keypad. | ||
292 | |||
293 | To compile this driver as a module, choose M here: the | ||
294 | module will be called bf54x-keys. | ||
295 | |||
256 | endif | 296 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 28d211b87b14..e97455fdcc83 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -21,4 +21,7 @@ obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | |||
21 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o | 21 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o |
22 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | 22 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
23 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | 23 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o |
24 | 24 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | |
25 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | ||
26 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | ||
27 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | ||
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c new file mode 100644 index 000000000000..a67b29b089ef --- /dev/null +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -0,0 +1,382 @@ | |||
1 | /* | ||
2 | * File: drivers/input/keyboard/bf54x-keys.c | ||
3 | * Based on: | ||
4 | * Author: Michael Hennerich <hennerich@blackfin.uclinux.org> | ||
5 | * | ||
6 | * Created: | ||
7 | * Description: keypad driver for Analog Devices Blackfin BF54x Processors | ||
8 | * | ||
9 | * | ||
10 | * Modified: | ||
11 | * Copyright 2007 Analog Devices Inc. | ||
12 | * | ||
13 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, see the file COPYING, or write | ||
27 | * to the Free Software Foundation, Inc., | ||
28 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
29 | */ | ||
30 | |||
31 | #include <linux/module.h> | ||
32 | #include <linux/version.h> | ||
33 | |||
34 | #include <linux/init.h> | ||
35 | #include <linux/fs.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/irq.h> | ||
38 | #include <linux/sched.h> | ||
39 | #include <linux/pm.h> | ||
40 | #include <linux/sysctl.h> | ||
41 | #include <linux/proc_fs.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include <linux/platform_device.h> | ||
44 | #include <linux/input.h> | ||
45 | #include <linux/irq.h> | ||
46 | |||
47 | #include <asm/portmux.h> | ||
48 | #include <asm/mach/bf54x_keys.h> | ||
49 | |||
50 | #define DRV_NAME "bf54x-keys" | ||
51 | #define TIME_SCALE 100 /* 100 ns */ | ||
52 | #define MAX_MULT (0xFF * TIME_SCALE) | ||
53 | #define MAX_RC 8 /* Max Row/Col */ | ||
54 | |||
55 | static const u16 per_rows[] = { | ||
56 | P_KEY_ROW7, | ||
57 | P_KEY_ROW6, | ||
58 | P_KEY_ROW5, | ||
59 | P_KEY_ROW4, | ||
60 | P_KEY_ROW3, | ||
61 | P_KEY_ROW2, | ||
62 | P_KEY_ROW1, | ||
63 | P_KEY_ROW0, | ||
64 | 0 | ||
65 | }; | ||
66 | |||
67 | static const u16 per_cols[] = { | ||
68 | P_KEY_COL7, | ||
69 | P_KEY_COL6, | ||
70 | P_KEY_COL5, | ||
71 | P_KEY_COL4, | ||
72 | P_KEY_COL3, | ||
73 | P_KEY_COL2, | ||
74 | P_KEY_COL1, | ||
75 | P_KEY_COL0, | ||
76 | 0 | ||
77 | }; | ||
78 | |||
79 | struct bf54x_kpad { | ||
80 | struct input_dev *input; | ||
81 | int irq; | ||
82 | unsigned short lastkey; | ||
83 | unsigned short *keycode; | ||
84 | struct timer_list timer; | ||
85 | unsigned int keyup_test_jiffies; | ||
86 | }; | ||
87 | |||
88 | static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad, | ||
89 | struct input_dev *input, u16 keyident) | ||
90 | { | ||
91 | u16 i; | ||
92 | |||
93 | for (i = 0; i < input->keycodemax; i++) | ||
94 | if (bf54x_kpad->keycode[i + input->keycodemax] == keyident) | ||
95 | return bf54x_kpad->keycode[i]; | ||
96 | return -1; | ||
97 | } | ||
98 | |||
99 | static inline void bfin_keycodecpy(unsigned short *keycode, | ||
100 | const unsigned int *pdata_kc, | ||
101 | unsigned short keymapsize) | ||
102 | { | ||
103 | unsigned int i; | ||
104 | |||
105 | for (i = 0; i < keymapsize; i++) { | ||
106 | keycode[i] = pdata_kc[i] & 0xffff; | ||
107 | keycode[i + keymapsize] = pdata_kc[i] >> 16; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static inline u16 bfin_kpad_get_prescale(u32 timescale) | ||
112 | { | ||
113 | u32 sclk = get_sclk(); | ||
114 | |||
115 | return ((((sclk / 1000) * timescale) / 1024) - 1); | ||
116 | } | ||
117 | |||
118 | static inline u16 bfin_kpad_get_keypressed(struct bf54x_kpad *bf54x_kpad) | ||
119 | { | ||
120 | return (bfin_read_KPAD_STAT() & KPAD_PRESSED); | ||
121 | } | ||
122 | |||
123 | static inline void bfin_kpad_clear_irq(void) | ||
124 | { | ||
125 | bfin_write_KPAD_STAT(0xFFFF); | ||
126 | bfin_write_KPAD_ROWCOL(0xFFFF); | ||
127 | } | ||
128 | |||
129 | static void bfin_kpad_timer(unsigned long data) | ||
130 | { | ||
131 | struct platform_device *pdev = (struct platform_device *) data; | ||
132 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
133 | |||
134 | if (bfin_kpad_get_keypressed(bf54x_kpad)) { | ||
135 | /* Try again later */ | ||
136 | mod_timer(&bf54x_kpad->timer, | ||
137 | jiffies + bf54x_kpad->keyup_test_jiffies); | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | input_report_key(bf54x_kpad->input, bf54x_kpad->lastkey, 0); | ||
142 | input_sync(bf54x_kpad->input); | ||
143 | |||
144 | /* Clear IRQ Status */ | ||
145 | |||
146 | bfin_kpad_clear_irq(); | ||
147 | enable_irq(bf54x_kpad->irq); | ||
148 | } | ||
149 | |||
150 | static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) | ||
151 | { | ||
152 | struct platform_device *pdev = dev_id; | ||
153 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
154 | struct input_dev *input = bf54x_kpad->input; | ||
155 | int key; | ||
156 | u16 rowcol = bfin_read_KPAD_ROWCOL(); | ||
157 | |||
158 | key = bfin_kpad_find_key(bf54x_kpad, input, rowcol); | ||
159 | |||
160 | input_report_key(input, key, 1); | ||
161 | input_sync(input); | ||
162 | |||
163 | if (bfin_kpad_get_keypressed(bf54x_kpad)) { | ||
164 | disable_irq(bf54x_kpad->irq); | ||
165 | bf54x_kpad->lastkey = key; | ||
166 | mod_timer(&bf54x_kpad->timer, | ||
167 | jiffies + bf54x_kpad->keyup_test_jiffies); | ||
168 | } else { | ||
169 | input_report_key(input, key, 0); | ||
170 | input_sync(input); | ||
171 | |||
172 | bfin_kpad_clear_irq(); | ||
173 | } | ||
174 | |||
175 | return IRQ_HANDLED; | ||
176 | } | ||
177 | |||
178 | static int __devinit bfin_kpad_probe(struct platform_device *pdev) | ||
179 | { | ||
180 | struct bf54x_kpad *bf54x_kpad; | ||
181 | struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; | ||
182 | struct input_dev *input; | ||
183 | int i, error; | ||
184 | |||
185 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { | ||
186 | printk(KERN_ERR DRV_NAME | ||
187 | ": No rows, cols or keymap from pdata\n"); | ||
188 | return -EINVAL; | ||
189 | } | ||
190 | |||
191 | if (!pdata->keymapsize || | ||
192 | pdata->keymapsize > (pdata->rows * pdata->cols)) { | ||
193 | printk(KERN_ERR DRV_NAME ": Invalid keymapsize\n"); | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | bf54x_kpad = kzalloc(sizeof(struct bf54x_kpad), GFP_KERNEL); | ||
198 | if (!bf54x_kpad) | ||
199 | return -ENOMEM; | ||
200 | |||
201 | platform_set_drvdata(pdev, bf54x_kpad); | ||
202 | |||
203 | /* Allocate memory for keymap followed by private LUT */ | ||
204 | bf54x_kpad->keycode = kmalloc(pdata->keymapsize * | ||
205 | sizeof(unsigned short) * 2, GFP_KERNEL); | ||
206 | if (!bf54x_kpad->keycode) { | ||
207 | error = -ENOMEM; | ||
208 | goto out; | ||
209 | } | ||
210 | |||
211 | if (!pdata->debounce_time || !pdata->debounce_time > MAX_MULT || | ||
212 | !pdata->coldrive_time || !pdata->coldrive_time > MAX_MULT) { | ||
213 | printk(KERN_ERR DRV_NAME | ||
214 | ": Invalid Debounce/Columdrive Time from pdata\n"); | ||
215 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | ||
216 | } else { | ||
217 | bfin_write_KPAD_MSEL( | ||
218 | ((pdata->debounce_time / TIME_SCALE) | ||
219 | & DBON_SCALE) | | ||
220 | (((pdata->coldrive_time / TIME_SCALE) << 8) | ||
221 | & COLDRV_SCALE)); | ||
222 | |||
223 | } | ||
224 | |||
225 | if (!pdata->keyup_test_interval) | ||
226 | bf54x_kpad->keyup_test_jiffies = msecs_to_jiffies(50); | ||
227 | else | ||
228 | bf54x_kpad->keyup_test_jiffies = | ||
229 | msecs_to_jiffies(pdata->keyup_test_interval); | ||
230 | |||
231 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], | ||
232 | DRV_NAME)) { | ||
233 | printk(KERN_ERR DRV_NAME | ||
234 | ": Requesting Peripherals failed\n"); | ||
235 | error = -EFAULT; | ||
236 | goto out0; | ||
237 | } | ||
238 | |||
239 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], | ||
240 | DRV_NAME)) { | ||
241 | printk(KERN_ERR DRV_NAME | ||
242 | ": Requesting Peripherals failed\n"); | ||
243 | error = -EFAULT; | ||
244 | goto out1; | ||
245 | } | ||
246 | |||
247 | bf54x_kpad->irq = platform_get_irq(pdev, 0); | ||
248 | if (bf54x_kpad->irq < 0) { | ||
249 | error = -ENODEV; | ||
250 | goto out2; | ||
251 | } | ||
252 | |||
253 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, | ||
254 | IRQF_SAMPLE_RANDOM, DRV_NAME, pdev); | ||
255 | if (error) { | ||
256 | printk(KERN_ERR DRV_NAME | ||
257 | ": unable to claim irq %d; error %d\n", | ||
258 | bf54x_kpad->irq, error); | ||
259 | error = -EBUSY; | ||
260 | goto out2; | ||
261 | } | ||
262 | |||
263 | input = input_allocate_device(); | ||
264 | if (!input) { | ||
265 | error = -ENOMEM; | ||
266 | goto out3; | ||
267 | } | ||
268 | |||
269 | bf54x_kpad->input = input; | ||
270 | |||
271 | input->name = pdev->name; | ||
272 | input->phys = "bf54x-keys/input0"; | ||
273 | input->dev.parent = &pdev->dev; | ||
274 | |||
275 | input_set_drvdata(input, bf54x_kpad); | ||
276 | |||
277 | input->id.bustype = BUS_HOST; | ||
278 | input->id.vendor = 0x0001; | ||
279 | input->id.product = 0x0001; | ||
280 | input->id.version = 0x0100; | ||
281 | |||
282 | input->keycodesize = sizeof(unsigned short); | ||
283 | input->keycodemax = pdata->keymapsize; | ||
284 | input->keycode = bf54x_kpad->keycode; | ||
285 | |||
286 | bfin_keycodecpy(bf54x_kpad->keycode, pdata->keymap, pdata->keymapsize); | ||
287 | |||
288 | /* setup input device */ | ||
289 | __set_bit(EV_KEY, input->evbit); | ||
290 | |||
291 | if (pdata->repeat) | ||
292 | __set_bit(EV_REP, input->evbit); | ||
293 | |||
294 | for (i = 0; i < input->keycodemax; i++) | ||
295 | __set_bit(bf54x_kpad->keycode[i] & KEY_MAX, input->keybit); | ||
296 | __clear_bit(KEY_RESERVED, input->keybit); | ||
297 | |||
298 | error = input_register_device(input); | ||
299 | if (error) { | ||
300 | printk(KERN_ERR DRV_NAME | ||
301 | ": Unable to register input device (%d)\n", error); | ||
302 | goto out4; | ||
303 | } | ||
304 | |||
305 | /* Init Keypad Key Up/Release test timer */ | ||
306 | |||
307 | setup_timer(&bf54x_kpad->timer, bfin_kpad_timer, (unsigned long) pdev); | ||
308 | |||
309 | bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE)); | ||
310 | |||
311 | bfin_write_KPAD_CTL((((pdata->cols - 1) << 13) & KPAD_COLEN) | | ||
312 | (((pdata->rows - 1) << 10) & KPAD_ROWEN) | | ||
313 | (2 & KPAD_IRQMODE)); | ||
314 | |||
315 | bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN); | ||
316 | |||
317 | printk(KERN_ERR DRV_NAME | ||
318 | ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq); | ||
319 | |||
320 | return 0; | ||
321 | |||
322 | out4: | ||
323 | input_free_device(input); | ||
324 | out3: | ||
325 | free_irq(bf54x_kpad->irq, pdev); | ||
326 | out2: | ||
327 | peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); | ||
328 | out1: | ||
329 | peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); | ||
330 | out0: | ||
331 | kfree(bf54x_kpad->keycode); | ||
332 | out: | ||
333 | kfree(bf54x_kpad); | ||
334 | platform_set_drvdata(pdev, NULL); | ||
335 | |||
336 | return error; | ||
337 | } | ||
338 | |||
339 | static int __devexit bfin_kpad_remove(struct platform_device *pdev) | ||
340 | { | ||
341 | struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; | ||
342 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
343 | |||
344 | del_timer_sync(&bf54x_kpad->timer); | ||
345 | free_irq(bf54x_kpad->irq, pdev); | ||
346 | |||
347 | input_unregister_device(bf54x_kpad->input); | ||
348 | |||
349 | peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); | ||
350 | peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); | ||
351 | |||
352 | kfree(bf54x_kpad->keycode); | ||
353 | kfree(bf54x_kpad); | ||
354 | platform_set_drvdata(pdev, NULL); | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | struct platform_driver bfin_kpad_device_driver = { | ||
360 | .probe = bfin_kpad_probe, | ||
361 | .remove = __devexit_p(bfin_kpad_remove), | ||
362 | .driver = { | ||
363 | .name = DRV_NAME, | ||
364 | } | ||
365 | }; | ||
366 | |||
367 | static int __init bfin_kpad_init(void) | ||
368 | { | ||
369 | return platform_driver_register(&bfin_kpad_device_driver); | ||
370 | } | ||
371 | |||
372 | static void __exit bfin_kpad_exit(void) | ||
373 | { | ||
374 | platform_driver_unregister(&bfin_kpad_device_driver); | ||
375 | } | ||
376 | |||
377 | module_init(bfin_kpad_init); | ||
378 | module_exit(bfin_kpad_exit); | ||
379 | |||
380 | MODULE_LICENSE("GPL"); | ||
381 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
382 | MODULE_DESCRIPTION("Keypad driver for BF54x Processors"); | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index f0b22b8b2769..e2a3293bc67e 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -54,6 +54,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
54 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 54 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
55 | struct input_dev *input; | 55 | struct input_dev *input; |
56 | int i, error; | 56 | int i, error; |
57 | int wakeup = 0; | ||
57 | 58 | ||
58 | input = input_allocate_device(); | 59 | input = input_allocate_device(); |
59 | if (!input) | 60 | if (!input) |
@@ -77,31 +78,51 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
77 | int irq = gpio_to_irq(button->gpio); | 78 | int irq = gpio_to_irq(button->gpio); |
78 | unsigned int type = button->type ?: EV_KEY; | 79 | unsigned int type = button->type ?: EV_KEY; |
79 | 80 | ||
80 | set_irq_type(irq, IRQ_TYPE_EDGE_BOTH); | 81 | if (irq < 0) { |
81 | error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM, | 82 | error = irq; |
82 | button->desc ? button->desc : "gpio_keys", | 83 | printk(KERN_ERR |
83 | pdev); | 84 | "gpio-keys: " |
85 | "Unable to get irq number for GPIO %d," | ||
86 | "error %d\n", | ||
87 | button->gpio, error); | ||
88 | goto fail; | ||
89 | } | ||
90 | |||
91 | error = request_irq(irq, gpio_keys_isr, | ||
92 | IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | | ||
93 | IRQF_TRIGGER_FALLING, | ||
94 | button->desc ? button->desc : "gpio_keys", | ||
95 | pdev); | ||
84 | if (error) { | 96 | if (error) { |
85 | printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n", | 97 | printk(KERN_ERR |
98 | "gpio-keys: Unable to claim irq %d; error %d\n", | ||
86 | irq, error); | 99 | irq, error); |
87 | goto fail; | 100 | goto fail; |
88 | } | 101 | } |
89 | 102 | ||
103 | if (button->wakeup) | ||
104 | wakeup = 1; | ||
105 | |||
90 | input_set_capability(input, type, button->code); | 106 | input_set_capability(input, type, button->code); |
91 | } | 107 | } |
92 | 108 | ||
93 | error = input_register_device(input); | 109 | error = input_register_device(input); |
94 | if (error) { | 110 | if (error) { |
95 | printk(KERN_ERR "Unable to register gpio-keys input device\n"); | 111 | printk(KERN_ERR |
112 | "gpio-keys: Unable to register input device, " | ||
113 | "error: %d\n", error); | ||
96 | goto fail; | 114 | goto fail; |
97 | } | 115 | } |
98 | 116 | ||
117 | device_init_wakeup(&pdev->dev, wakeup); | ||
118 | |||
99 | return 0; | 119 | return 0; |
100 | 120 | ||
101 | fail: | 121 | fail: |
102 | for (i = i - 1; i >= 0; i--) | 122 | while (--i >= 0) |
103 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); | 123 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); |
104 | 124 | ||
125 | platform_set_drvdata(pdev, NULL); | ||
105 | input_free_device(input); | 126 | input_free_device(input); |
106 | 127 | ||
107 | return error; | 128 | return error; |
@@ -113,6 +134,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
113 | struct input_dev *input = platform_get_drvdata(pdev); | 134 | struct input_dev *input = platform_get_drvdata(pdev); |
114 | int i; | 135 | int i; |
115 | 136 | ||
137 | device_init_wakeup(&pdev->dev, 0); | ||
138 | |||
116 | for (i = 0; i < pdata->nbuttons; i++) { | 139 | for (i = 0; i < pdata->nbuttons; i++) { |
117 | int irq = gpio_to_irq(pdata->buttons[i].gpio); | 140 | int irq = gpio_to_irq(pdata->buttons[i].gpio); |
118 | free_irq(irq, pdev); | 141 | free_irq(irq, pdev); |
@@ -123,9 +146,53 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
123 | return 0; | 146 | return 0; |
124 | } | 147 | } |
125 | 148 | ||
149 | |||
150 | #ifdef CONFIG_PM | ||
151 | static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) | ||
152 | { | ||
153 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
154 | int i; | ||
155 | |||
156 | if (device_may_wakeup(&pdev->dev)) { | ||
157 | for (i = 0; i < pdata->nbuttons; i++) { | ||
158 | struct gpio_keys_button *button = &pdata->buttons[i]; | ||
159 | if (button->wakeup) { | ||
160 | int irq = gpio_to_irq(button->gpio); | ||
161 | enable_irq_wake(irq); | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int gpio_keys_resume(struct platform_device *pdev) | ||
170 | { | ||
171 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
172 | int i; | ||
173 | |||
174 | if (device_may_wakeup(&pdev->dev)) { | ||
175 | for (i = 0; i < pdata->nbuttons; i++) { | ||
176 | struct gpio_keys_button *button = &pdata->buttons[i]; | ||
177 | if (button->wakeup) { | ||
178 | int irq = gpio_to_irq(button->gpio); | ||
179 | disable_irq_wake(irq); | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | #else | ||
187 | #define gpio_keys_suspend NULL | ||
188 | #define gpio_keys_resume NULL | ||
189 | #endif | ||
190 | |||
126 | struct platform_driver gpio_keys_device_driver = { | 191 | struct platform_driver gpio_keys_device_driver = { |
127 | .probe = gpio_keys_probe, | 192 | .probe = gpio_keys_probe, |
128 | .remove = __devexit_p(gpio_keys_remove), | 193 | .remove = __devexit_p(gpio_keys_remove), |
194 | .suspend = gpio_keys_suspend, | ||
195 | .resume = gpio_keys_resume, | ||
129 | .driver = { | 196 | .driver = { |
130 | .name = "gpio-keys", | 197 | .name = "gpio-keys", |
131 | } | 198 | } |
diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c new file mode 100644 index 000000000000..bec1cf483723 --- /dev/null +++ b/drivers/input/keyboard/jornada680_kbd.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * drivers/input/keyboard/jornada680_kbd.c | ||
3 | * | ||
4 | * HP Jornada 620/660/680/690 scan keyboard platform driver | ||
5 | * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com> | ||
6 | * | ||
7 | * Based on hp680_keyb.c | ||
8 | * Copyright (C) 2006 Paul Mundt | ||
9 | * Copyright (C) 2005 Andriy Skulysh | ||
10 | * Split from drivers/input/keyboard/hp600_keyb.c | ||
11 | * Copyright (C) 2000 Yaegashi Takeshi (hp6xx kbd scan routine and translation table) | ||
12 | * Copyright (C) 2000 Niibe Yutaka (HP620 Keyb translation table) | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #include <linux/input.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/input-polldev.h> | ||
24 | #include <linux/jiffies.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | |||
28 | #include <asm/delay.h> | ||
29 | #include <asm/io.h> | ||
30 | |||
31 | #define PCCR 0xa4000104 | ||
32 | #define PDCR 0xa4000106 | ||
33 | #define PECR 0xa4000108 | ||
34 | #define PFCR 0xa400010a | ||
35 | #define PCDR 0xa4000124 | ||
36 | #define PDDR 0xa4000126 | ||
37 | #define PEDR 0xa4000128 | ||
38 | #define PFDR 0xa400012a | ||
39 | #define PGDR 0xa400012c | ||
40 | #define PHDR 0xa400012e | ||
41 | #define PJDR 0xa4000130 | ||
42 | #define PKDR 0xa4000132 | ||
43 | #define PLDR 0xa4000134 | ||
44 | |||
45 | static const unsigned short jornada_scancodes[] = { | ||
46 | /* PTD1 */ KEY_CAPSLOCK, KEY_MACRO, KEY_LEFTCTRL, 0, KEY_ESC, 0, 0, 0, /* 1 -> 8 */ | ||
47 | KEY_F1, KEY_F2, KEY_F3, KEY_F8, KEY_F7, KEY_F2, KEY_F4, KEY_F5, /* 9 -> 16 */ | ||
48 | /* PTD5 */ KEY_SLASH, KEY_APOSTROPHE, KEY_ENTER, 0, KEY_Z, 0, 0, 0, /* 17 -> 24 */ | ||
49 | KEY_X, KEY_C, KEY_V, KEY_DOT, KEY_COMMA, KEY_M, KEY_B, KEY_N, /* 25 -> 32 */ | ||
50 | /* PTD7 */ KEY_KP2, KEY_KP6, 0, 0, 0, 0, 0, 0, /* 33 -> 40 */ | ||
51 | 0, 0, 0, KEY_KP4, 0, 0, KEY_LEFTALT, KEY_HANJA, /* 41 -> 48 */ | ||
52 | /* PTE0 */ 0, 0, 0, 0, KEY_FINANCE, 0, 0, 0, /* 49 -> 56 */ | ||
53 | KEY_LEFTCTRL, 0, KEY_SPACE, KEY_KPDOT, KEY_VOLUMEUP, 249, 0, 0, /* 57 -> 64 */ | ||
54 | /* PTE1 */ KEY_SEMICOLON, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, KEY_A, 0, 0, 0,/* 65 -> 72 */ | ||
55 | KEY_S, KEY_D, KEY_F, KEY_L, KEY_K, KEY_J, KEY_G, KEY_H, /* 73 -> 80 */ | ||
56 | /* PTE3 */ KEY_KP8, KEY_LEFTMETA, KEY_RIGHTSHIFT, 0, KEY_TAB, 0, 0,0, /* 81 -> 88 */ | ||
57 | 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 89 -> 96 */ | ||
58 | /* PTE6 */ KEY_P, KEY_LEFTBRACE, KEY_BACKSPACE, 0, KEY_Q, 0, 0, 0, /* 97 -> 104 */ | ||
59 | KEY_W, KEY_E, KEY_R, KEY_O, KEY_I, KEY_U, KEY_T, KEY_R, /* 105 -> 112 */ | ||
60 | /* PTE7 */ KEY_0, KEY_MINUS, KEY_EQUAL, 0, KEY_1, 0, 0, 0, /* 113 -> 120 */ | ||
61 | KEY_2, KEY_3, KEY_4, KEY_9, KEY_8, KEY_7, KEY_5, KEY_6, /* 121 -> 128 */ | ||
62 | /* **** */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
63 | 0, 0, 0, 0, 0 | ||
64 | }; | ||
65 | |||
66 | #define JORNADA_SCAN_SIZE 18 | ||
67 | |||
68 | struct jornadakbd { | ||
69 | struct input_polled_dev *poll_dev; | ||
70 | unsigned short keymap[ARRAY_SIZE(jornada_scancodes)]; | ||
71 | unsigned char length; | ||
72 | unsigned char old_scan[JORNADA_SCAN_SIZE]; | ||
73 | unsigned char new_scan[JORNADA_SCAN_SIZE]; | ||
74 | }; | ||
75 | |||
76 | static void jornada_parse_kbd(struct jornadakbd *jornadakbd) | ||
77 | { | ||
78 | struct input_dev *input_dev = jornadakbd->poll_dev->input; | ||
79 | unsigned short *keymap = jornadakbd->keymap; | ||
80 | unsigned int sync_me = 0; | ||
81 | unsigned int i, j; | ||
82 | |||
83 | for (i = 0; i < JORNADA_SCAN_SIZE; i++) { | ||
84 | unsigned char new = jornadakbd->new_scan[i]; | ||
85 | unsigned char old = jornadakbd->old_scan[i]; | ||
86 | unsigned int xor = new ^ old; | ||
87 | |||
88 | if (xor == 0) | ||
89 | continue; | ||
90 | |||
91 | for (j = 0; j < 8; j++) { | ||
92 | unsigned int bit = 1 << j; | ||
93 | if (xor & bit) { | ||
94 | unsigned int scancode = (i << 3) + j; | ||
95 | input_event(input_dev, | ||
96 | EV_MSC, MSC_SCAN, scancode); | ||
97 | input_report_key(input_dev, | ||
98 | keymap[scancode], | ||
99 | !(new & bit)); | ||
100 | sync_me = 1; | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | if (sync_me) | ||
106 | input_sync(input_dev); | ||
107 | } | ||
108 | |||
109 | static void jornada_scan_keyb(unsigned char *s) | ||
110 | { | ||
111 | int i; | ||
112 | unsigned short ec_static, dc_static; /* = UINT16_t */ | ||
113 | unsigned char matrix_switch[] = { | ||
114 | 0xfd, 0xff, /* PTD1 PD(1) */ | ||
115 | 0xdf, 0xff, /* PTD5 PD(5) */ | ||
116 | 0x7f, 0xff, /* PTD7 PD(7) */ | ||
117 | 0xff, 0xfe, /* PTE0 PE(0) */ | ||
118 | 0xff, 0xfd, /* PTE1 PE(1) */ | ||
119 | 0xff, 0xf7, /* PTE3 PE(3) */ | ||
120 | 0xff, 0xbf, /* PTE6 PE(6) */ | ||
121 | 0xff, 0x7f, /* PTE7 PE(7) */ | ||
122 | }, *t = matrix_switch; | ||
123 | /* PD(x) : | ||
124 | 1. 0xcc0c & (1~(1 << (2*(x)+1))))) | ||
125 | 2. (0xf0cf & 0xfffff) */ | ||
126 | /* PE(x) : | ||
127 | 1. 0xcc0c & 0xffff | ||
128 | 2. 0xf0cf & (1~(1 << (2*(x)+1))))) */ | ||
129 | unsigned short matrix_PDE[] = { | ||
130 | 0xcc04, 0xf0cf, /* PD(1) */ | ||
131 | 0xc40c, 0xf0cf, /* PD(5) */ | ||
132 | 0x4c0c, 0xf0cf, /* PD(7) */ | ||
133 | 0xcc0c, 0xf0cd, /* PE(0) */ | ||
134 | 0xcc0c, 0xf0c7, /* PE(1) */ | ||
135 | 0xcc0c, 0xf04f, /* PE(3) */ | ||
136 | 0xcc0c, 0xd0cf, /* PE(6) */ | ||
137 | 0xcc0c, 0x70cf, /* PE(7) */ | ||
138 | }, *y = matrix_PDE; | ||
139 | |||
140 | /* Save these control reg bits */ | ||
141 | dc_static = (ctrl_inw(PDCR) & (~0xcc0c)); | ||
142 | ec_static = (ctrl_inw(PECR) & (~0xf0cf)); | ||
143 | |||
144 | for (i = 0; i < 8; i++) { | ||
145 | /* disable output for all but the one we want to scan */ | ||
146 | ctrl_outw((dc_static | *y++), PDCR); | ||
147 | ctrl_outw((ec_static | *y++), PECR); | ||
148 | udelay(5); | ||
149 | |||
150 | /* Get scanline row */ | ||
151 | ctrl_outb(*t++, PDDR); | ||
152 | ctrl_outb(*t++, PEDR); | ||
153 | udelay(50); | ||
154 | |||
155 | /* Read data */ | ||
156 | *s++ = ctrl_inb(PCDR); | ||
157 | *s++ = ctrl_inb(PFDR); | ||
158 | } | ||
159 | /* Scan no lines */ | ||
160 | ctrl_outb(0xff, PDDR); | ||
161 | ctrl_outb(0xff, PEDR); | ||
162 | |||
163 | /* Enable all scanlines */ | ||
164 | ctrl_outw((dc_static | (0x5555 & 0xcc0c)),PDCR); | ||
165 | ctrl_outw((ec_static | (0x5555 & 0xf0cf)),PECR); | ||
166 | |||
167 | /* Ignore extra keys and events */ | ||
168 | *s++ = ctrl_inb(PGDR); | ||
169 | *s++ = ctrl_inb(PHDR); | ||
170 | } | ||
171 | |||
172 | static void jornadakbd680_poll(struct input_polled_dev *dev) | ||
173 | { | ||
174 | struct jornadakbd *jornadakbd = dev->private; | ||
175 | |||
176 | jornada_scan_keyb(jornadakbd->new_scan); | ||
177 | jornada_parse_kbd(jornadakbd); | ||
178 | memcpy(jornadakbd->old_scan, jornadakbd->new_scan, JORNADA_SCAN_SIZE); | ||
179 | } | ||
180 | |||
181 | static int __devinit jornada680kbd_probe(struct platform_device *pdev) | ||
182 | { | ||
183 | struct jornadakbd *jornadakbd; | ||
184 | struct input_polled_dev *poll_dev; | ||
185 | struct input_dev *input_dev; | ||
186 | int i, error; | ||
187 | |||
188 | jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL); | ||
189 | if (!jornadakbd) | ||
190 | return -ENOMEM; | ||
191 | |||
192 | poll_dev = input_allocate_polled_device(); | ||
193 | if (!poll_dev) { | ||
194 | error = -ENOMEM; | ||
195 | goto failed; | ||
196 | } | ||
197 | |||
198 | platform_set_drvdata(pdev, jornadakbd); | ||
199 | |||
200 | jornadakbd->poll_dev = poll_dev; | ||
201 | |||
202 | memcpy(jornadakbd->keymap, jornada_scancodes, | ||
203 | sizeof(jornadakbd->keymap)); | ||
204 | |||
205 | poll_dev->private = jornadakbd; | ||
206 | poll_dev->poll = jornadakbd680_poll; | ||
207 | poll_dev->poll_interval = 50; /* msec */ | ||
208 | |||
209 | input_dev = poll_dev->input; | ||
210 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
211 | input_dev->name = "HP Jornada 680 keyboard"; | ||
212 | input_dev->phys = "jornadakbd/input0"; | ||
213 | input_dev->keycode = jornadakbd->keymap; | ||
214 | input_dev->keycodesize = sizeof(unsigned short); | ||
215 | input_dev->keycodemax = ARRAY_SIZE(jornada_scancodes); | ||
216 | input_dev->dev.parent = &pdev->dev; | ||
217 | input_dev->id.bustype = BUS_HOST; | ||
218 | |||
219 | for (i = 0; i < 128; i++) | ||
220 | if (jornadakbd->keymap[i]) | ||
221 | __set_bit(jornadakbd->keymap[i], input_dev->keybit); | ||
222 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
223 | |||
224 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
225 | |||
226 | error = input_register_polled_device(jornadakbd->poll_dev); | ||
227 | if (error) | ||
228 | goto failed; | ||
229 | |||
230 | return 0; | ||
231 | |||
232 | failed: | ||
233 | printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n", | ||
234 | error); | ||
235 | platform_set_drvdata(pdev, NULL); | ||
236 | input_free_polled_device(poll_dev); | ||
237 | kfree(jornadakbd); | ||
238 | return error; | ||
239 | |||
240 | } | ||
241 | |||
242 | static int __devexit jornada680kbd_remove(struct platform_device *pdev) | ||
243 | { | ||
244 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
245 | |||
246 | platform_set_drvdata(pdev, NULL); | ||
247 | input_unregister_polled_device(jornadakbd->poll_dev); | ||
248 | input_free_polled_device(jornadakbd->poll_dev); | ||
249 | kfree(jornadakbd); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static struct platform_driver jornada680kbd_driver = { | ||
255 | .driver = { | ||
256 | .name = "jornada680_kbd", | ||
257 | }, | ||
258 | .probe = jornada680kbd_probe, | ||
259 | .remove = __devexit_p(jornada680kbd_remove), | ||
260 | }; | ||
261 | |||
262 | static int __init jornada680kbd_init(void) | ||
263 | { | ||
264 | return platform_driver_register(&jornada680kbd_driver); | ||
265 | } | ||
266 | |||
267 | static void __exit jornada680kbd_exit(void) | ||
268 | { | ||
269 | platform_driver_unregister(&jornada680kbd_driver); | ||
270 | } | ||
271 | |||
272 | module_init(jornada680kbd_init); | ||
273 | module_exit(jornada680kbd_exit); | ||
274 | |||
275 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); | ||
276 | MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver"); | ||
277 | MODULE_LICENSE("GPLv2"); | ||
diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c new file mode 100644 index 000000000000..e6696b3c9416 --- /dev/null +++ b/drivers/input/keyboard/jornada720_kbd.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * drivers/input/keyboard/jornada720_kbd.c | ||
3 | * | ||
4 | * HP Jornada 720 keyboard platform driver | ||
5 | * | ||
6 | * Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@Gmail.com> | ||
7 | * | ||
8 | * Copyright (C) 2006 jornada 720 kbd driver by | ||
9 | Filip Zyzniewsk <Filip.Zyzniewski@tefnet.plX | ||
10 | * based on (C) 2004 jornada 720 kbd driver by | ||
11 | Alex Lange <chicken@handhelds.org> | ||
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 version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/input.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | |||
28 | #include <asm/arch/jornada720.h> | ||
29 | #include <asm/hardware.h> | ||
30 | |||
31 | MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>"); | ||
32 | MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver"); | ||
33 | MODULE_LICENSE("GPLv2"); | ||
34 | |||
35 | static unsigned short jornada_std_keymap[128] = { /* ROW */ | ||
36 | 0, KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, /* #1 */ | ||
37 | KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, /* -> */ | ||
38 | 0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, /* #2 */ | ||
39 | KEY_0, KEY_MINUS, KEY_EQUAL,0, 0, 0, /* -> */ | ||
40 | 0, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, /* #3 */ | ||
41 | KEY_P, KEY_BACKSLASH, KEY_BACKSPACE, 0, 0, 0, /* -> */ | ||
42 | 0, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, /* #4 */ | ||
43 | KEY_SEMICOLON, KEY_LEFTBRACE, KEY_RIGHTBRACE, 0, 0, 0, /* -> */ | ||
44 | 0, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, /* #5 */ | ||
45 | KEY_DOT, KEY_KPMINUS, KEY_APOSTROPHE, KEY_ENTER, 0, 0,0, /* -> */ | ||
46 | 0, KEY_TAB, 0, KEY_LEFTSHIFT, 0, KEY_APOSTROPHE, 0, 0, 0, 0, /* #6 */ | ||
47 | KEY_UP, 0, KEY_RIGHTSHIFT, 0, 0, 0,0, 0, 0, 0, 0, KEY_LEFTALT, KEY_GRAVE, /* -> */ | ||
48 | 0, 0, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0,0, KEY_KPASTERISK, /* -> */ | ||
49 | KEY_LEFTCTRL, 0, KEY_SPACE, 0, 0, 0, KEY_SLASH, KEY_DELETE, 0, 0, /* -> */ | ||
50 | 0, 0, 0, KEY_POWER, /* -> */ | ||
51 | }; | ||
52 | |||
53 | struct jornadakbd { | ||
54 | unsigned short keymap[ARRAY_SIZE(jornada_std_keymap)]; | ||
55 | struct input_dev *input; | ||
56 | }; | ||
57 | |||
58 | static irqreturn_t jornada720_kbd_interrupt(int irq, void *dev_id) | ||
59 | { | ||
60 | struct platform_device *pdev = dev_id; | ||
61 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
62 | struct input_dev *input = jornadakbd->input; | ||
63 | u8 count, kbd_data, scan_code; | ||
64 | |||
65 | /* startup ssp with spinlock */ | ||
66 | jornada_ssp_start(); | ||
67 | |||
68 | if (jornada_ssp_inout(GETSCANKEYCODE) != TXDUMMY) { | ||
69 | printk(KERN_DEBUG | ||
70 | "jornada720_kbd: " | ||
71 | "GetKeycode command failed with ETIMEDOUT, " | ||
72 | "flushed bus\n"); | ||
73 | } else { | ||
74 | /* How many keycodes are waiting for us? */ | ||
75 | count = jornada_ssp_byte(TXDUMMY); | ||
76 | |||
77 | /* Lets drag them out one at a time */ | ||
78 | while (count--) { | ||
79 | /* Exchange TxDummy for location (keymap[kbddata]) */ | ||
80 | kbd_data = jornada_ssp_byte(TXDUMMY); | ||
81 | scan_code = kbd_data & 0x7f; | ||
82 | |||
83 | input_event(input, EV_MSC, MSC_SCAN, scan_code); | ||
84 | input_report_key(input, jornadakbd->keymap[scan_code], | ||
85 | !(kbd_data & 0x80)); | ||
86 | input_sync(input); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | /* release spinlock and turn off ssp */ | ||
91 | jornada_ssp_end(); | ||
92 | |||
93 | return IRQ_HANDLED; | ||
94 | }; | ||
95 | |||
96 | static int __devinit jornada720_kbd_probe(struct platform_device *pdev) | ||
97 | { | ||
98 | struct jornadakbd *jornadakbd; | ||
99 | struct input_dev *input_dev; | ||
100 | int i, err; | ||
101 | |||
102 | jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL); | ||
103 | input_dev = input_allocate_device(); | ||
104 | if (!jornadakbd || !input_dev) { | ||
105 | err = -ENOMEM; | ||
106 | goto fail1; | ||
107 | } | ||
108 | |||
109 | platform_set_drvdata(pdev, jornadakbd); | ||
110 | |||
111 | memcpy(jornadakbd->keymap, jornada_std_keymap, | ||
112 | sizeof(jornada_std_keymap)); | ||
113 | jornadakbd->input = input_dev; | ||
114 | |||
115 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
116 | input_dev->name = "HP Jornada 720 keyboard"; | ||
117 | input_dev->phys = "jornadakbd/input0"; | ||
118 | input_dev->keycode = jornadakbd->keymap; | ||
119 | input_dev->keycodesize = sizeof(unsigned short); | ||
120 | input_dev->keycodemax = ARRAY_SIZE(jornada_std_keymap); | ||
121 | input_dev->id.bustype = BUS_HOST; | ||
122 | input_dev->dev.parent = &pdev->dev; | ||
123 | |||
124 | for (i = 0; i < ARRAY_SIZE(jornadakbd->keymap); i++) | ||
125 | __set_bit(jornadakbd->keymap[i], input_dev->keybit); | ||
126 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
127 | |||
128 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
129 | |||
130 | err = request_irq(IRQ_GPIO0, | ||
131 | jornada720_kbd_interrupt, | ||
132 | IRQF_DISABLED | IRQF_TRIGGER_FALLING, | ||
133 | "jornadakbd", pdev); | ||
134 | if (err) { | ||
135 | printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n"); | ||
136 | goto fail1; | ||
137 | } | ||
138 | |||
139 | err = input_register_device(jornadakbd->input); | ||
140 | if (err) | ||
141 | goto fail2; | ||
142 | |||
143 | return 0; | ||
144 | |||
145 | fail2: /* IRQ, DEVICE, MEMORY */ | ||
146 | free_irq(IRQ_GPIO0, pdev); | ||
147 | fail1: /* DEVICE, MEMORY */ | ||
148 | platform_set_drvdata(pdev, NULL); | ||
149 | input_free_device(input_dev); | ||
150 | kfree(jornadakbd); | ||
151 | return err; | ||
152 | }; | ||
153 | |||
154 | static int __devexit jornada720_kbd_remove(struct platform_device *pdev) | ||
155 | { | ||
156 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
157 | |||
158 | free_irq(IRQ_GPIO0, pdev); | ||
159 | platform_set_drvdata(pdev, NULL); | ||
160 | input_unregister_device(jornadakbd->input); | ||
161 | kfree(jornadakbd); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static struct platform_driver jornada720_kbd_driver = { | ||
167 | .driver = { | ||
168 | .name = "jornada720_kbd", | ||
169 | }, | ||
170 | .probe = jornada720_kbd_probe, | ||
171 | .remove = __devexit_p(jornada720_kbd_remove), | ||
172 | }; | ||
173 | |||
174 | static int __init jornada720_kbd_init(void) | ||
175 | { | ||
176 | return platform_driver_register(&jornada720_kbd_driver); | ||
177 | } | ||
178 | |||
179 | static void __exit jornada720_kbd_exit(void) | ||
180 | { | ||
181 | platform_driver_unregister(&jornada720_kbd_driver); | ||
182 | } | ||
183 | |||
184 | module_init(jornada720_kbd_init); | ||
185 | module_exit(jornada720_kbd_exit); | ||
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c new file mode 100644 index 000000000000..2b404284c28a --- /dev/null +++ b/drivers/input/keyboard/maple_keyb.c | |||
@@ -0,0 +1,252 @@ | |||
1 | /* | ||
2 | * SEGA Dreamcast keyboard driver | ||
3 | * Based on drivers/usb/usbkbd.c | ||
4 | * Copyright YAEGASHI Takeshi, 2001 | ||
5 | * Porting to 2.6 Copyright Adrian McMenamin, 2007 | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, see the file COPYING, or write | ||
19 | * to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/input.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/timer.h> | ||
29 | #include <linux/maple.h> | ||
30 | #include <asm/mach/maple.h> | ||
31 | |||
32 | /* Very simple mutex to ensure proper cleanup */ | ||
33 | static DEFINE_MUTEX(maple_keyb_mutex); | ||
34 | |||
35 | #define NR_SCANCODES 256 | ||
36 | |||
37 | MODULE_AUTHOR("YAEGASHI Takeshi, Adrian McMenamin"); | ||
38 | MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver"); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | struct dc_kbd { | ||
42 | struct input_dev *dev; | ||
43 | unsigned short keycode[NR_SCANCODES]; | ||
44 | unsigned char new[8]; | ||
45 | unsigned char old[8]; | ||
46 | }; | ||
47 | |||
48 | static const unsigned short dc_kbd_keycode[NR_SCANCODES] = { | ||
49 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A, KEY_B, KEY_C, KEY_D, | ||
50 | KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, | ||
51 | KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, | ||
52 | KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2, | ||
53 | KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, | ||
54 | KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE, | ||
55 | KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, | ||
56 | KEY_DOT, KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, | ||
57 | KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ, | ||
58 | KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE, | ||
59 | KEY_END, KEY_PAGEDOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP, | ||
60 | KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS, KEY_KPENTER, KEY_KP1, KEY_KP2, | ||
61 | KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT, | ||
62 | KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15, | ||
63 | KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20, | ||
64 | KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT, | ||
65 | KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE, | ||
66 | KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_KPCOMMA, KEY_RESERVED, KEY_RO, KEY_KATAKANAHIRAGANA , KEY_YEN, | ||
67 | KEY_HENKAN, KEY_MUHENKAN, KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
68 | KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA, KEY_ZENKAKUHANKAKU, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
69 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
70 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
71 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
72 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
73 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
74 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
75 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
76 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
77 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
78 | KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA, | ||
79 | KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG, KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, | ||
80 | KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP, | ||
81 | KEY_SCREENLOCK, KEY_REFRESH, KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED | ||
82 | }; | ||
83 | |||
84 | static void dc_scan_kbd(struct dc_kbd *kbd) | ||
85 | { | ||
86 | struct input_dev *dev = kbd->dev; | ||
87 | void *ptr; | ||
88 | int code, keycode; | ||
89 | int i; | ||
90 | |||
91 | for (i = 0; i < 8; i++) { | ||
92 | code = i + 224; | ||
93 | keycode = kbd->keycode[code]; | ||
94 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
95 | input_report_key(dev, keycode, (kbd->new[0] >> i) & 1); | ||
96 | } | ||
97 | |||
98 | for (i = 2; i < 8; i++) { | ||
99 | ptr = memchr(kbd->new + 2, kbd->old[i], 6); | ||
100 | code = kbd->old[i]; | ||
101 | if (code > 3 && ptr == NULL) { | ||
102 | keycode = kbd->keycode[code]; | ||
103 | if (keycode) { | ||
104 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
105 | input_report_key(dev, keycode, 0); | ||
106 | } else | ||
107 | printk(KERN_DEBUG "maple_keyb: " | ||
108 | "Unknown key (scancode %#x) released.", | ||
109 | code); | ||
110 | } | ||
111 | ptr = memchr(kbd->old + 2, kbd->new[i], 6); | ||
112 | code = kbd->new[i]; | ||
113 | if (code > 3 && ptr) { | ||
114 | keycode = kbd->keycode[code]; | ||
115 | if (keycode) { | ||
116 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
117 | input_report_key(dev, keycode, 1); | ||
118 | } else | ||
119 | printk(KERN_DEBUG "maple_keyb: " | ||
120 | "Unknown key (scancode %#x) pressed.", | ||
121 | code); | ||
122 | } | ||
123 | } | ||
124 | input_sync(dev); | ||
125 | memcpy(kbd->old, kbd->new, 8); | ||
126 | } | ||
127 | |||
128 | static void dc_kbd_callback(struct mapleq *mq) | ||
129 | { | ||
130 | struct maple_device *mapledev = mq->dev; | ||
131 | struct dc_kbd *kbd = mapledev->private_data; | ||
132 | unsigned long *buf = mq->recvbuf; | ||
133 | |||
134 | /* | ||
135 | * We should always be getting the lock because the only | ||
136 | * time it may be locked if driver is in cleanup phase. | ||
137 | */ | ||
138 | if (likely(mutex_trylock(&maple_keyb_mutex))) { | ||
139 | |||
140 | if (buf[1] == mapledev->function) { | ||
141 | memcpy(kbd->new, buf + 2, 8); | ||
142 | dc_scan_kbd(kbd); | ||
143 | } | ||
144 | |||
145 | mutex_unlock(&maple_keyb_mutex); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | static int dc_kbd_connect(struct maple_device *mdev) | ||
150 | { | ||
151 | int i, error; | ||
152 | struct dc_kbd *kbd; | ||
153 | struct input_dev *dev; | ||
154 | |||
155 | if (!(mdev->function & MAPLE_FUNC_KEYBOARD)) | ||
156 | return -EINVAL; | ||
157 | |||
158 | kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); | ||
159 | dev = input_allocate_device(); | ||
160 | if (!kbd || !dev) { | ||
161 | error = -ENOMEM; | ||
162 | goto fail; | ||
163 | } | ||
164 | |||
165 | mdev->private_data = kbd; | ||
166 | |||
167 | kbd->dev = dev; | ||
168 | memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode)); | ||
169 | |||
170 | dev->name = mdev->product_name; | ||
171 | dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
172 | dev->keycode = kbd->keycode; | ||
173 | dev->keycodesize = sizeof (unsigned short); | ||
174 | dev->keycodemax = ARRAY_SIZE(kbd->keycode); | ||
175 | dev->id.bustype = BUS_HOST; | ||
176 | dev->dev.parent = &mdev->dev; | ||
177 | |||
178 | for (i = 0; i < NR_SCANCODES; i++) | ||
179 | __set_bit(dc_kbd_keycode[i], dev->keybit); | ||
180 | __clear_bit(KEY_RESERVED, dev->keybit); | ||
181 | |||
182 | input_set_capability(dev, EV_MSC, MSC_SCAN); | ||
183 | input_set_drvdata(dev, kbd); | ||
184 | |||
185 | error = input_register_device(dev); | ||
186 | if (error) | ||
187 | goto fail; | ||
188 | |||
189 | /* Maple polling is locked to VBLANK - which may be just 50/s */ | ||
190 | maple_getcond_callback(mdev, dc_kbd_callback, HZ/50, MAPLE_FUNC_KEYBOARD); | ||
191 | return 0; | ||
192 | |||
193 | fail: | ||
194 | input_free_device(dev); | ||
195 | kfree(kbd); | ||
196 | mdev->private_data = NULL; | ||
197 | return error; | ||
198 | } | ||
199 | |||
200 | static void dc_kbd_disconnect(struct maple_device *mdev) | ||
201 | { | ||
202 | struct dc_kbd *kbd; | ||
203 | |||
204 | mutex_lock(&maple_keyb_mutex); | ||
205 | |||
206 | kbd = mdev->private_data; | ||
207 | mdev->private_data = NULL; | ||
208 | input_unregister_device(kbd->dev); | ||
209 | kfree(kbd); | ||
210 | |||
211 | mutex_unlock(&maple_keyb_mutex); | ||
212 | } | ||
213 | |||
214 | /* allow the keyboard to be used */ | ||
215 | static int probe_maple_kbd(struct device *dev) | ||
216 | { | ||
217 | struct maple_device *mdev = to_maple_dev(dev); | ||
218 | struct maple_driver *mdrv = to_maple_driver(dev->driver); | ||
219 | int error; | ||
220 | |||
221 | error = dc_kbd_connect(mdev); | ||
222 | if (error) | ||
223 | return error; | ||
224 | |||
225 | mdev->driver = mdrv; | ||
226 | mdev->registered = 1; | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static struct maple_driver dc_kbd_driver = { | ||
232 | .function = MAPLE_FUNC_KEYBOARD, | ||
233 | .connect = dc_kbd_connect, | ||
234 | .disconnect = dc_kbd_disconnect, | ||
235 | .drv = { | ||
236 | .name = "Dreamcast_keyboard", | ||
237 | .probe = probe_maple_kbd, | ||
238 | }, | ||
239 | }; | ||
240 | |||
241 | static int __init dc_kbd_init(void) | ||
242 | { | ||
243 | return maple_driver_register(&dc_kbd_driver.drv); | ||
244 | } | ||
245 | |||
246 | static void __exit dc_kbd_exit(void) | ||
247 | { | ||
248 | driver_unregister(&dc_kbd_driver.drv); | ||
249 | } | ||
250 | |||
251 | module_init(dc_kbd_init); | ||
252 | module_exit(dc_kbd_exit); | ||
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 3a228634f101..76f1969552c5 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
@@ -233,7 +233,7 @@ static void omap_kp_tasklet(unsigned long data) | |||
233 | omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 233 | omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
234 | kp_cur_group = -1; | 234 | kp_cur_group = -1; |
235 | } | 235 | } |
236 | } | 236 | } |
237 | } | 237 | } |
238 | 238 | ||
239 | static ssize_t omap_kp_enable_show(struct device *dev, | 239 | static ssize_t omap_kp_enable_show(struct device *dev, |
@@ -318,7 +318,7 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
318 | keymap = pdata->keymap; | 318 | keymap = pdata->keymap; |
319 | 319 | ||
320 | if (pdata->rep) | 320 | if (pdata->rep) |
321 | set_bit(EV_REP, input_dev->evbit); | 321 | __set_bit(EV_REP, input_dev->evbit); |
322 | 322 | ||
323 | if (pdata->delay) | 323 | if (pdata->delay) |
324 | omap_kp->delay = pdata->delay; | 324 | omap_kp->delay = pdata->delay; |
@@ -365,9 +365,9 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
365 | goto err2; | 365 | goto err2; |
366 | 366 | ||
367 | /* setup input device */ | 367 | /* setup input device */ |
368 | set_bit(EV_KEY, input_dev->evbit); | 368 | __set_bit(EV_KEY, input_dev->evbit); |
369 | for (i = 0; keymap[i] != 0; i++) | 369 | for (i = 0; keymap[i] != 0; i++) |
370 | set_bit(keymap[i] & KEY_MAX, input_dev->keybit); | 370 | __set_bit(keymap[i] & KEY_MAX, input_dev->keybit); |
371 | input_dev->name = "omap-keypad"; | 371 | input_dev->name = "omap-keypad"; |
372 | input_dev->phys = "omap-keypad/input0"; | 372 | input_dev->phys = "omap-keypad/input0"; |
373 | input_dev->dev.parent = &pdev->dev; | 373 | input_dev->dev.parent = &pdev->dev; |
@@ -377,10 +377,6 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
377 | input_dev->id.product = 0x0001; | 377 | input_dev->id.product = 0x0001; |
378 | input_dev->id.version = 0x0100; | 378 | input_dev->id.version = 0x0100; |
379 | 379 | ||
380 | input_dev->keycode = keymap; | ||
381 | input_dev->keycodesize = sizeof(unsigned int); | ||
382 | input_dev->keycodemax = pdata->keymapsize; | ||
383 | |||
384 | ret = input_register_device(omap_kp->input); | 380 | ret = input_register_device(omap_kp->input); |
385 | if (ret < 0) { | 381 | if (ret < 0) { |
386 | printk(KERN_ERR "Unable to register omap-keypad input device\n"); | 382 | printk(KERN_ERR "Unable to register omap-keypad input device\n"); |
@@ -403,15 +399,15 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
403 | } else { | 399 | } else { |
404 | for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { | 400 | for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { |
405 | if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]), | 401 | if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]), |
406 | omap_kp_interrupt, | 402 | omap_kp_interrupt, |
407 | IRQF_TRIGGER_FALLING, | 403 | IRQF_TRIGGER_FALLING, |
408 | "omap-keypad", omap_kp) < 0) | 404 | "omap-keypad", omap_kp) < 0) |
409 | goto err5; | 405 | goto err5; |
410 | } | 406 | } |
411 | } | 407 | } |
412 | return 0; | 408 | return 0; |
413 | err5: | 409 | err5: |
414 | for (i = irq_idx-1; i >=0; i--) | 410 | for (i = irq_idx - 1; i >=0; i--) |
415 | free_irq(row_gpios[i], 0); | 411 | free_irq(row_gpios[i], 0); |
416 | err4: | 412 | err4: |
417 | input_unregister_device(omap_kp->input); | 413 | input_unregister_device(omap_kp->input); |
@@ -440,9 +436,9 @@ static int omap_kp_remove(struct platform_device *pdev) | |||
440 | if (cpu_is_omap24xx()) { | 436 | if (cpu_is_omap24xx()) { |
441 | int i; | 437 | int i; |
442 | for (i = 0; i < omap_kp->cols; i++) | 438 | for (i = 0; i < omap_kp->cols; i++) |
443 | omap_free_gpio(col_gpios[i]); | 439 | omap_free_gpio(col_gpios[i]); |
444 | for (i = 0; i < omap_kp->rows; i++) { | 440 | for (i = 0; i < omap_kp->rows; i++) { |
445 | omap_free_gpio(row_gpios[i]); | 441 | omap_free_gpio(row_gpios[i]); |
446 | free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); | 442 | free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); |
447 | } | 443 | } |
448 | } else { | 444 | } else { |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 2c5f11a4f6b4..64d70a9b714c 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -48,11 +48,13 @@ static const struct alps_model_info alps_model_data[] = { | |||
48 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ | 48 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ |
49 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, | 49 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, |
50 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ | 50 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ |
51 | { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ | ||
51 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, | 52 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, |
52 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ | 53 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ |
53 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 54 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
54 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 55 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
55 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 56 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
57 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xff, ALPS_FW_BK_1 } /* Dell Vostro 1400 */ | ||
56 | }; | 58 | }; |
57 | 59 | ||
58 | /* | 60 | /* |
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index a1804bfdbb8c..0117817bf538 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -502,18 +502,23 @@ static void atp_complete(struct urb* urb) | |||
502 | 502 | ||
503 | /* reset the accumulator on release */ | 503 | /* reset the accumulator on release */ |
504 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); | 504 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); |
505 | } | ||
506 | |||
507 | /* Geyser 3 will continue to send packets continually after | ||
508 | the first touch unless reinitialised. Do so if it's been | ||
509 | idle for a while in order to avoid waking the kernel up | ||
510 | several hundred times a second */ | ||
505 | 511 | ||
506 | /* Geyser 3 will continue to send packets continually after | 512 | if (atp_is_geyser_3(dev)) { |
507 | the first touch unless reinitialised. Do so if it's been | 513 | if (!x && !y && !key) { |
508 | idle for a while in order to avoid waking the kernel up | ||
509 | several hundred times a second */ | ||
510 | if (!key && atp_is_geyser_3(dev)) { | ||
511 | dev->idlecount++; | 514 | dev->idlecount++; |
512 | if (dev->idlecount == 10) { | 515 | if (dev->idlecount == 10) { |
513 | dev->valid = 0; | 516 | dev->valid = 0; |
514 | schedule_work(&dev->work); | 517 | schedule_work(&dev->work); |
515 | } | 518 | } |
516 | } | 519 | } |
520 | else | ||
521 | dev->idlecount = 0; | ||
517 | } | 522 | } |
518 | 523 | ||
519 | input_report_key(dev->input, BTN_LEFT, key); | 524 | input_report_key(dev->input, BTN_LEFT, key); |
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 608674d0be8b..d7de4c53b3d8 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
@@ -97,6 +97,14 @@ static const struct dmi_system_id lifebook_dmi_table[] = { | |||
97 | .callback = lifebook_set_6byte_proto, | 97 | .callback = lifebook_set_6byte_proto, |
98 | }, | 98 | }, |
99 | { | 99 | { |
100 | .ident = "CF-72", | ||
101 | .matches = { | ||
102 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"), | ||
103 | }, | ||
104 | .callback = lifebook_set_serio_phys, | ||
105 | .driver_data = "isa0060/serio3", | ||
106 | }, | ||
107 | { | ||
100 | .ident = "Lifebook B142", | 108 | .ident = "Lifebook B142", |
101 | .matches = { | 109 | .matches = { |
102 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), | 110 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), |
@@ -282,7 +290,7 @@ static int lifebook_create_relative_device(struct psmouse *psmouse) | |||
282 | int lifebook_init(struct psmouse *psmouse) | 290 | int lifebook_init(struct psmouse *psmouse) |
283 | { | 291 | { |
284 | struct input_dev *dev1 = psmouse->dev; | 292 | struct input_dev *dev1 = psmouse->dev; |
285 | int max_coord = lifebook_use_6byte_proto ? 1024 : 4096; | 293 | int max_coord = lifebook_use_6byte_proto ? 4096 : 1024; |
286 | 294 | ||
287 | if (lifebook_absolute_mode(psmouse)) | 295 | if (lifebook_absolute_mode(psmouse)) |
288 | return -1; | 296 | return -1; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index b9f0fb2530e2..073525756532 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -648,9 +648,10 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
648 | 648 | ||
649 | /* | 649 | /* |
650 | * Reset to defaults in case the device got confused by extended | 650 | * Reset to defaults in case the device got confused by extended |
651 | * protocol probes. Note that we do full reset becuase some mice | 651 | * protocol probes. Note that we follow up with full reset because |
652 | * put themselves to sleep when see PSMOUSE_RESET_DIS. | 652 | * some mice put themselves to sleep when they see PSMOUSE_RESET_DIS. |
653 | */ | 653 | */ |
654 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); | ||
654 | psmouse_reset(psmouse); | 655 | psmouse_reset(psmouse); |
655 | 656 | ||
656 | if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0) | 657 | if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0) |
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 9173916b8be5..79146d6ed2ab 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
@@ -61,9 +61,11 @@ struct mousedev { | |||
61 | int open; | 61 | int open; |
62 | int minor; | 62 | int minor; |
63 | char name[16]; | 63 | char name[16]; |
64 | struct input_handle handle; | ||
64 | wait_queue_head_t wait; | 65 | wait_queue_head_t wait; |
65 | struct list_head client_list; | 66 | struct list_head client_list; |
66 | struct input_handle handle; | 67 | spinlock_t client_lock; /* protects client_list */ |
68 | struct mutex mutex; | ||
67 | struct device dev; | 69 | struct device dev; |
68 | 70 | ||
69 | struct list_head mixdev_node; | 71 | struct list_head mixdev_node; |
@@ -113,108 +115,137 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; | |||
113 | static struct input_handler mousedev_handler; | 115 | static struct input_handler mousedev_handler; |
114 | 116 | ||
115 | static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; | 117 | static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; |
118 | static DEFINE_MUTEX(mousedev_table_mutex); | ||
116 | static struct mousedev *mousedev_mix; | 119 | static struct mousedev *mousedev_mix; |
117 | static LIST_HEAD(mousedev_mix_list); | 120 | static LIST_HEAD(mousedev_mix_list); |
118 | 121 | ||
122 | static void mixdev_open_devices(void); | ||
123 | static void mixdev_close_devices(void); | ||
124 | |||
119 | #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) | 125 | #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) |
120 | #define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03]) | 126 | #define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03]) |
121 | 127 | ||
122 | static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value) | 128 | static void mousedev_touchpad_event(struct input_dev *dev, |
129 | struct mousedev *mousedev, | ||
130 | unsigned int code, int value) | ||
123 | { | 131 | { |
124 | int size, tmp; | 132 | int size, tmp; |
125 | enum { FRACTION_DENOM = 128 }; | 133 | enum { FRACTION_DENOM = 128 }; |
126 | 134 | ||
127 | switch (code) { | 135 | switch (code) { |
128 | case ABS_X: | ||
129 | fx(0) = value; | ||
130 | if (mousedev->touch && mousedev->pkt_count >= 2) { | ||
131 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; | ||
132 | if (size == 0) | ||
133 | size = 256 * 2; | ||
134 | tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size; | ||
135 | tmp += mousedev->frac_dx; | ||
136 | mousedev->packet.dx = tmp / FRACTION_DENOM; | ||
137 | mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM; | ||
138 | } | ||
139 | break; | ||
140 | 136 | ||
141 | case ABS_Y: | 137 | case ABS_X: |
142 | fy(0) = value; | 138 | fx(0) = value; |
143 | if (mousedev->touch && mousedev->pkt_count >= 2) { | 139 | if (mousedev->touch && mousedev->pkt_count >= 2) { |
144 | /* use X size to keep the same scale */ | 140 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; |
145 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; | 141 | if (size == 0) |
146 | if (size == 0) | 142 | size = 256 * 2; |
147 | size = 256 * 2; | 143 | tmp = ((value - fx(2)) * 256 * FRACTION_DENOM) / size; |
148 | tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size; | 144 | tmp += mousedev->frac_dx; |
149 | tmp += mousedev->frac_dy; | 145 | mousedev->packet.dx = tmp / FRACTION_DENOM; |
150 | mousedev->packet.dy = tmp / FRACTION_DENOM; | 146 | mousedev->frac_dx = |
151 | mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM; | 147 | tmp - mousedev->packet.dx * FRACTION_DENOM; |
152 | } | 148 | } |
153 | break; | 149 | break; |
150 | |||
151 | case ABS_Y: | ||
152 | fy(0) = value; | ||
153 | if (mousedev->touch && mousedev->pkt_count >= 2) { | ||
154 | /* use X size to keep the same scale */ | ||
155 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; | ||
156 | if (size == 0) | ||
157 | size = 256 * 2; | ||
158 | tmp = -((value - fy(2)) * 256 * FRACTION_DENOM) / size; | ||
159 | tmp += mousedev->frac_dy; | ||
160 | mousedev->packet.dy = tmp / FRACTION_DENOM; | ||
161 | mousedev->frac_dy = tmp - | ||
162 | mousedev->packet.dy * FRACTION_DENOM; | ||
163 | } | ||
164 | break; | ||
154 | } | 165 | } |
155 | } | 166 | } |
156 | 167 | ||
157 | static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value) | 168 | static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, |
169 | unsigned int code, int value) | ||
158 | { | 170 | { |
159 | int size; | 171 | int size; |
160 | 172 | ||
161 | switch (code) { | 173 | switch (code) { |
162 | case ABS_X: | ||
163 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; | ||
164 | if (size == 0) | ||
165 | size = xres ? : 1; | ||
166 | if (value > dev->absmax[ABS_X]) | ||
167 | value = dev->absmax[ABS_X]; | ||
168 | if (value < dev->absmin[ABS_X]) | ||
169 | value = dev->absmin[ABS_X]; | ||
170 | mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size; | ||
171 | mousedev->packet.abs_event = 1; | ||
172 | break; | ||
173 | 174 | ||
174 | case ABS_Y: | 175 | case ABS_X: |
175 | size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; | 176 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; |
176 | if (size == 0) | 177 | if (size == 0) |
177 | size = yres ? : 1; | 178 | size = xres ? : 1; |
178 | if (value > dev->absmax[ABS_Y]) | 179 | if (value > dev->absmax[ABS_X]) |
179 | value = dev->absmax[ABS_Y]; | 180 | value = dev->absmax[ABS_X]; |
180 | if (value < dev->absmin[ABS_Y]) | 181 | if (value < dev->absmin[ABS_X]) |
181 | value = dev->absmin[ABS_Y]; | 182 | value = dev->absmin[ABS_X]; |
182 | mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size; | 183 | mousedev->packet.x = |
183 | mousedev->packet.abs_event = 1; | 184 | ((value - dev->absmin[ABS_X]) * xres) / size; |
184 | break; | 185 | mousedev->packet.abs_event = 1; |
186 | break; | ||
187 | |||
188 | case ABS_Y: | ||
189 | size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; | ||
190 | if (size == 0) | ||
191 | size = yres ? : 1; | ||
192 | if (value > dev->absmax[ABS_Y]) | ||
193 | value = dev->absmax[ABS_Y]; | ||
194 | if (value < dev->absmin[ABS_Y]) | ||
195 | value = dev->absmin[ABS_Y]; | ||
196 | mousedev->packet.y = yres - | ||
197 | ((value - dev->absmin[ABS_Y]) * yres) / size; | ||
198 | mousedev->packet.abs_event = 1; | ||
199 | break; | ||
185 | } | 200 | } |
186 | } | 201 | } |
187 | 202 | ||
188 | static void mousedev_rel_event(struct mousedev *mousedev, unsigned int code, int value) | 203 | static void mousedev_rel_event(struct mousedev *mousedev, |
204 | unsigned int code, int value) | ||
189 | { | 205 | { |
190 | switch (code) { | 206 | switch (code) { |
191 | case REL_X: mousedev->packet.dx += value; break; | 207 | case REL_X: |
192 | case REL_Y: mousedev->packet.dy -= value; break; | 208 | mousedev->packet.dx += value; |
193 | case REL_WHEEL: mousedev->packet.dz -= value; break; | 209 | break; |
210 | |||
211 | case REL_Y: | ||
212 | mousedev->packet.dy -= value; | ||
213 | break; | ||
214 | |||
215 | case REL_WHEEL: | ||
216 | mousedev->packet.dz -= value; | ||
217 | break; | ||
194 | } | 218 | } |
195 | } | 219 | } |
196 | 220 | ||
197 | static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int value) | 221 | static void mousedev_key_event(struct mousedev *mousedev, |
222 | unsigned int code, int value) | ||
198 | { | 223 | { |
199 | int index; | 224 | int index; |
200 | 225 | ||
201 | switch (code) { | 226 | switch (code) { |
202 | case BTN_TOUCH: | 227 | |
203 | case BTN_0: | 228 | case BTN_TOUCH: |
204 | case BTN_LEFT: index = 0; break; | 229 | case BTN_0: |
205 | case BTN_STYLUS: | 230 | case BTN_LEFT: index = 0; break; |
206 | case BTN_1: | 231 | |
207 | case BTN_RIGHT: index = 1; break; | 232 | case BTN_STYLUS: |
208 | case BTN_2: | 233 | case BTN_1: |
209 | case BTN_FORWARD: | 234 | case BTN_RIGHT: index = 1; break; |
210 | case BTN_STYLUS2: | 235 | |
211 | case BTN_MIDDLE: index = 2; break; | 236 | case BTN_2: |
212 | case BTN_3: | 237 | case BTN_FORWARD: |
213 | case BTN_BACK: | 238 | case BTN_STYLUS2: |
214 | case BTN_SIDE: index = 3; break; | 239 | case BTN_MIDDLE: index = 2; break; |
215 | case BTN_4: | 240 | |
216 | case BTN_EXTRA: index = 4; break; | 241 | case BTN_3: |
217 | default: return; | 242 | case BTN_BACK: |
243 | case BTN_SIDE: index = 3; break; | ||
244 | |||
245 | case BTN_4: | ||
246 | case BTN_EXTRA: index = 4; break; | ||
247 | |||
248 | default: return; | ||
218 | } | 249 | } |
219 | 250 | ||
220 | if (value) { | 251 | if (value) { |
@@ -226,19 +257,23 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int | |||
226 | } | 257 | } |
227 | } | 258 | } |
228 | 259 | ||
229 | static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet) | 260 | static void mousedev_notify_readers(struct mousedev *mousedev, |
261 | struct mousedev_hw_data *packet) | ||
230 | { | 262 | { |
231 | struct mousedev_client *client; | 263 | struct mousedev_client *client; |
232 | struct mousedev_motion *p; | 264 | struct mousedev_motion *p; |
233 | unsigned long flags; | 265 | unsigned int new_head; |
234 | int wake_readers = 0; | 266 | int wake_readers = 0; |
235 | 267 | ||
236 | list_for_each_entry(client, &mousedev->client_list, node) { | 268 | rcu_read_lock(); |
237 | spin_lock_irqsave(&client->packet_lock, flags); | 269 | list_for_each_entry_rcu(client, &mousedev->client_list, node) { |
270 | |||
271 | /* Just acquire the lock, interrupts already disabled */ | ||
272 | spin_lock(&client->packet_lock); | ||
238 | 273 | ||
239 | p = &client->packets[client->head]; | 274 | p = &client->packets[client->head]; |
240 | if (client->ready && p->buttons != mousedev->packet.buttons) { | 275 | if (client->ready && p->buttons != mousedev->packet.buttons) { |
241 | unsigned int new_head = (client->head + 1) % PACKET_QUEUE_LEN; | 276 | new_head = (client->head + 1) % PACKET_QUEUE_LEN; |
242 | if (new_head != client->tail) { | 277 | if (new_head != client->tail) { |
243 | p = &client->packets[client->head = new_head]; | 278 | p = &client->packets[client->head = new_head]; |
244 | memset(p, 0, sizeof(struct mousedev_motion)); | 279 | memset(p, 0, sizeof(struct mousedev_motion)); |
@@ -253,25 +288,29 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h | |||
253 | } | 288 | } |
254 | 289 | ||
255 | client->pos_x += packet->dx; | 290 | client->pos_x += packet->dx; |
256 | client->pos_x = client->pos_x < 0 ? 0 : (client->pos_x >= xres ? xres : client->pos_x); | 291 | client->pos_x = client->pos_x < 0 ? |
292 | 0 : (client->pos_x >= xres ? xres : client->pos_x); | ||
257 | client->pos_y += packet->dy; | 293 | client->pos_y += packet->dy; |
258 | client->pos_y = client->pos_y < 0 ? 0 : (client->pos_y >= yres ? yres : client->pos_y); | 294 | client->pos_y = client->pos_y < 0 ? |
295 | 0 : (client->pos_y >= yres ? yres : client->pos_y); | ||
259 | 296 | ||
260 | p->dx += packet->dx; | 297 | p->dx += packet->dx; |
261 | p->dy += packet->dy; | 298 | p->dy += packet->dy; |
262 | p->dz += packet->dz; | 299 | p->dz += packet->dz; |
263 | p->buttons = mousedev->packet.buttons; | 300 | p->buttons = mousedev->packet.buttons; |
264 | 301 | ||
265 | if (p->dx || p->dy || p->dz || p->buttons != client->last_buttons) | 302 | if (p->dx || p->dy || p->dz || |
303 | p->buttons != client->last_buttons) | ||
266 | client->ready = 1; | 304 | client->ready = 1; |
267 | 305 | ||
268 | spin_unlock_irqrestore(&client->packet_lock, flags); | 306 | spin_unlock(&client->packet_lock); |
269 | 307 | ||
270 | if (client->ready) { | 308 | if (client->ready) { |
271 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | 309 | kill_fasync(&client->fasync, SIGIO, POLL_IN); |
272 | wake_readers = 1; | 310 | wake_readers = 1; |
273 | } | 311 | } |
274 | } | 312 | } |
313 | rcu_read_unlock(); | ||
275 | 314 | ||
276 | if (wake_readers) | 315 | if (wake_readers) |
277 | wake_up_interruptible(&mousedev->wait); | 316 | wake_up_interruptible(&mousedev->wait); |
@@ -281,7 +320,8 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) | |||
281 | { | 320 | { |
282 | if (!value) { | 321 | if (!value) { |
283 | if (mousedev->touch && | 322 | if (mousedev->touch && |
284 | time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) { | 323 | time_before(jiffies, |
324 | mousedev->touch + msecs_to_jiffies(tap_time))) { | ||
285 | /* | 325 | /* |
286 | * Toggle left button to emulate tap. | 326 | * Toggle left button to emulate tap. |
287 | * We rely on the fact that mousedev_mix always has 0 | 327 | * We rely on the fact that mousedev_mix always has 0 |
@@ -290,7 +330,8 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) | |||
290 | set_bit(0, &mousedev->packet.buttons); | 330 | set_bit(0, &mousedev->packet.buttons); |
291 | set_bit(0, &mousedev_mix->packet.buttons); | 331 | set_bit(0, &mousedev_mix->packet.buttons); |
292 | mousedev_notify_readers(mousedev, &mousedev_mix->packet); | 332 | mousedev_notify_readers(mousedev, &mousedev_mix->packet); |
293 | mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet); | 333 | mousedev_notify_readers(mousedev_mix, |
334 | &mousedev_mix->packet); | ||
294 | clear_bit(0, &mousedev->packet.buttons); | 335 | clear_bit(0, &mousedev->packet.buttons); |
295 | clear_bit(0, &mousedev_mix->packet.buttons); | 336 | clear_bit(0, &mousedev_mix->packet.buttons); |
296 | } | 337 | } |
@@ -302,54 +343,61 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) | |||
302 | mousedev->touch = jiffies; | 343 | mousedev->touch = jiffies; |
303 | } | 344 | } |
304 | 345 | ||
305 | static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 346 | static void mousedev_event(struct input_handle *handle, |
347 | unsigned int type, unsigned int code, int value) | ||
306 | { | 348 | { |
307 | struct mousedev *mousedev = handle->private; | 349 | struct mousedev *mousedev = handle->private; |
308 | 350 | ||
309 | switch (type) { | 351 | switch (type) { |
310 | case EV_ABS: | ||
311 | /* Ignore joysticks */ | ||
312 | if (test_bit(BTN_TRIGGER, handle->dev->keybit)) | ||
313 | return; | ||
314 | 352 | ||
315 | if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) | 353 | case EV_ABS: |
316 | mousedev_touchpad_event(handle->dev, mousedev, code, value); | 354 | /* Ignore joysticks */ |
317 | else | 355 | if (test_bit(BTN_TRIGGER, handle->dev->keybit)) |
318 | mousedev_abs_event(handle->dev, mousedev, code, value); | 356 | return; |
319 | 357 | ||
320 | break; | 358 | if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) |
359 | mousedev_touchpad_event(handle->dev, | ||
360 | mousedev, code, value); | ||
361 | else | ||
362 | mousedev_abs_event(handle->dev, mousedev, code, value); | ||
321 | 363 | ||
322 | case EV_REL: | 364 | break; |
323 | mousedev_rel_event(mousedev, code, value); | ||
324 | break; | ||
325 | 365 | ||
326 | case EV_KEY: | 366 | case EV_REL: |
327 | if (value != 2) { | 367 | mousedev_rel_event(mousedev, code, value); |
328 | if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) | 368 | break; |
329 | mousedev_touchpad_touch(mousedev, value); | ||
330 | else | ||
331 | mousedev_key_event(mousedev, code, value); | ||
332 | } | ||
333 | break; | ||
334 | 369 | ||
335 | case EV_SYN: | 370 | case EV_KEY: |
336 | if (code == SYN_REPORT) { | 371 | if (value != 2) { |
337 | if (mousedev->touch) { | 372 | if (code == BTN_TOUCH && |
338 | mousedev->pkt_count++; | 373 | test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) |
339 | /* Input system eats duplicate events, but we need all of them | 374 | mousedev_touchpad_touch(mousedev, value); |
340 | * to do correct averaging so apply present one forward | 375 | else |
341 | */ | 376 | mousedev_key_event(mousedev, code, value); |
342 | fx(0) = fx(1); | 377 | } |
343 | fy(0) = fy(1); | 378 | break; |
344 | } | 379 | |
345 | 380 | case EV_SYN: | |
346 | mousedev_notify_readers(mousedev, &mousedev->packet); | 381 | if (code == SYN_REPORT) { |
347 | mousedev_notify_readers(mousedev_mix, &mousedev->packet); | 382 | if (mousedev->touch) { |
348 | 383 | mousedev->pkt_count++; | |
349 | mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0; | 384 | /* |
350 | mousedev->packet.abs_event = 0; | 385 | * Input system eats duplicate events, |
386 | * but we need all of them to do correct | ||
387 | * averaging so apply present one forward | ||
388 | */ | ||
389 | fx(0) = fx(1); | ||
390 | fy(0) = fy(1); | ||
351 | } | 391 | } |
352 | break; | 392 | |
393 | mousedev_notify_readers(mousedev, &mousedev->packet); | ||
394 | mousedev_notify_readers(mousedev_mix, &mousedev->packet); | ||
395 | |||
396 | mousedev->packet.dx = mousedev->packet.dy = | ||
397 | mousedev->packet.dz = 0; | ||
398 | mousedev->packet.abs_event = 0; | ||
399 | } | ||
400 | break; | ||
353 | } | 401 | } |
354 | } | 402 | } |
355 | 403 | ||
@@ -367,41 +415,48 @@ static void mousedev_free(struct device *dev) | |||
367 | { | 415 | { |
368 | struct mousedev *mousedev = container_of(dev, struct mousedev, dev); | 416 | struct mousedev *mousedev = container_of(dev, struct mousedev, dev); |
369 | 417 | ||
370 | mousedev_table[mousedev->minor] = NULL; | ||
371 | kfree(mousedev); | 418 | kfree(mousedev); |
372 | } | 419 | } |
373 | 420 | ||
374 | static int mixdev_add_device(struct mousedev *mousedev) | 421 | static int mousedev_open_device(struct mousedev *mousedev) |
375 | { | 422 | { |
376 | int error; | 423 | int retval; |
377 | 424 | ||
378 | if (mousedev_mix->open) { | 425 | retval = mutex_lock_interruptible(&mousedev->mutex); |
379 | error = input_open_device(&mousedev->handle); | 426 | if (retval) |
380 | if (error) | 427 | return retval; |
381 | return error; | ||
382 | 428 | ||
383 | mousedev->open++; | 429 | if (mousedev->minor == MOUSEDEV_MIX) |
384 | mousedev->mixdev_open = 1; | 430 | mixdev_open_devices(); |
431 | else if (!mousedev->exist) | ||
432 | retval = -ENODEV; | ||
433 | else if (!mousedev->open++) { | ||
434 | retval = input_open_device(&mousedev->handle); | ||
435 | if (retval) | ||
436 | mousedev->open--; | ||
385 | } | 437 | } |
386 | 438 | ||
387 | get_device(&mousedev->dev); | 439 | mutex_unlock(&mousedev->mutex); |
388 | list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list); | 440 | return retval; |
389 | |||
390 | return 0; | ||
391 | } | 441 | } |
392 | 442 | ||
393 | static void mixdev_remove_device(struct mousedev *mousedev) | 443 | static void mousedev_close_device(struct mousedev *mousedev) |
394 | { | 444 | { |
395 | if (mousedev->mixdev_open) { | 445 | mutex_lock(&mousedev->mutex); |
396 | mousedev->mixdev_open = 0; | ||
397 | if (!--mousedev->open && mousedev->exist) | ||
398 | input_close_device(&mousedev->handle); | ||
399 | } | ||
400 | 446 | ||
401 | list_del_init(&mousedev->mixdev_node); | 447 | if (mousedev->minor == MOUSEDEV_MIX) |
402 | put_device(&mousedev->dev); | 448 | mixdev_close_devices(); |
449 | else if (mousedev->exist && !--mousedev->open) | ||
450 | input_close_device(&mousedev->handle); | ||
451 | |||
452 | mutex_unlock(&mousedev->mutex); | ||
403 | } | 453 | } |
404 | 454 | ||
455 | /* | ||
456 | * Open all available devices so they can all be multiplexed in one. | ||
457 | * stream. Note that this function is called with mousedev_mix->mutex | ||
458 | * held. | ||
459 | */ | ||
405 | static void mixdev_open_devices(void) | 460 | static void mixdev_open_devices(void) |
406 | { | 461 | { |
407 | struct mousedev *mousedev; | 462 | struct mousedev *mousedev; |
@@ -411,16 +466,19 @@ static void mixdev_open_devices(void) | |||
411 | 466 | ||
412 | list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { | 467 | list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { |
413 | if (!mousedev->mixdev_open) { | 468 | if (!mousedev->mixdev_open) { |
414 | if (!mousedev->open && mousedev->exist) | 469 | if (mousedev_open_device(mousedev)) |
415 | if (input_open_device(&mousedev->handle)) | 470 | continue; |
416 | continue; | ||
417 | 471 | ||
418 | mousedev->open++; | ||
419 | mousedev->mixdev_open = 1; | 472 | mousedev->mixdev_open = 1; |
420 | } | 473 | } |
421 | } | 474 | } |
422 | } | 475 | } |
423 | 476 | ||
477 | /* | ||
478 | * Close all devices that were opened as part of multiplexed | ||
479 | * device. Note that this function is called with mousedev_mix->mutex | ||
480 | * held. | ||
481 | */ | ||
424 | static void mixdev_close_devices(void) | 482 | static void mixdev_close_devices(void) |
425 | { | 483 | { |
426 | struct mousedev *mousedev; | 484 | struct mousedev *mousedev; |
@@ -431,33 +489,45 @@ static void mixdev_close_devices(void) | |||
431 | list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { | 489 | list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { |
432 | if (mousedev->mixdev_open) { | 490 | if (mousedev->mixdev_open) { |
433 | mousedev->mixdev_open = 0; | 491 | mousedev->mixdev_open = 0; |
434 | if (!--mousedev->open && mousedev->exist) | 492 | mousedev_close_device(mousedev); |
435 | input_close_device(&mousedev->handle); | ||
436 | } | 493 | } |
437 | } | 494 | } |
438 | } | 495 | } |
439 | 496 | ||
497 | |||
498 | static void mousedev_attach_client(struct mousedev *mousedev, | ||
499 | struct mousedev_client *client) | ||
500 | { | ||
501 | spin_lock(&mousedev->client_lock); | ||
502 | list_add_tail_rcu(&client->node, &mousedev->client_list); | ||
503 | spin_unlock(&mousedev->client_lock); | ||
504 | synchronize_rcu(); | ||
505 | } | ||
506 | |||
507 | static void mousedev_detach_client(struct mousedev *mousedev, | ||
508 | struct mousedev_client *client) | ||
509 | { | ||
510 | spin_lock(&mousedev->client_lock); | ||
511 | list_del_rcu(&client->node); | ||
512 | spin_unlock(&mousedev->client_lock); | ||
513 | synchronize_rcu(); | ||
514 | } | ||
515 | |||
440 | static int mousedev_release(struct inode *inode, struct file *file) | 516 | static int mousedev_release(struct inode *inode, struct file *file) |
441 | { | 517 | { |
442 | struct mousedev_client *client = file->private_data; | 518 | struct mousedev_client *client = file->private_data; |
443 | struct mousedev *mousedev = client->mousedev; | 519 | struct mousedev *mousedev = client->mousedev; |
444 | 520 | ||
445 | mousedev_fasync(-1, file, 0); | 521 | mousedev_fasync(-1, file, 0); |
446 | 522 | mousedev_detach_client(mousedev, client); | |
447 | list_del(&client->node); | ||
448 | kfree(client); | 523 | kfree(client); |
449 | 524 | ||
450 | if (mousedev->minor == MOUSEDEV_MIX) | 525 | mousedev_close_device(mousedev); |
451 | mixdev_close_devices(); | ||
452 | else if (!--mousedev->open && mousedev->exist) | ||
453 | input_close_device(&mousedev->handle); | ||
454 | |||
455 | put_device(&mousedev->dev); | 526 | put_device(&mousedev->dev); |
456 | 527 | ||
457 | return 0; | 528 | return 0; |
458 | } | 529 | } |
459 | 530 | ||
460 | |||
461 | static int mousedev_open(struct inode *inode, struct file *file) | 531 | static int mousedev_open(struct inode *inode, struct file *file) |
462 | { | 532 | { |
463 | struct mousedev_client *client; | 533 | struct mousedev_client *client; |
@@ -475,12 +545,17 @@ static int mousedev_open(struct inode *inode, struct file *file) | |||
475 | if (i >= MOUSEDEV_MINORS) | 545 | if (i >= MOUSEDEV_MINORS) |
476 | return -ENODEV; | 546 | return -ENODEV; |
477 | 547 | ||
548 | error = mutex_lock_interruptible(&mousedev_table_mutex); | ||
549 | if (error) | ||
550 | return error; | ||
478 | mousedev = mousedev_table[i]; | 551 | mousedev = mousedev_table[i]; |
552 | if (mousedev) | ||
553 | get_device(&mousedev->dev); | ||
554 | mutex_unlock(&mousedev_table_mutex); | ||
555 | |||
479 | if (!mousedev) | 556 | if (!mousedev) |
480 | return -ENODEV; | 557 | return -ENODEV; |
481 | 558 | ||
482 | get_device(&mousedev->dev); | ||
483 | |||
484 | client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); | 559 | client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); |
485 | if (!client) { | 560 | if (!client) { |
486 | error = -ENOMEM; | 561 | error = -ENOMEM; |
@@ -491,21 +566,17 @@ static int mousedev_open(struct inode *inode, struct file *file) | |||
491 | client->pos_x = xres / 2; | 566 | client->pos_x = xres / 2; |
492 | client->pos_y = yres / 2; | 567 | client->pos_y = yres / 2; |
493 | client->mousedev = mousedev; | 568 | client->mousedev = mousedev; |
494 | list_add_tail(&client->node, &mousedev->client_list); | 569 | mousedev_attach_client(mousedev, client); |
495 | 570 | ||
496 | if (mousedev->minor == MOUSEDEV_MIX) | 571 | error = mousedev_open_device(mousedev); |
497 | mixdev_open_devices(); | 572 | if (error) |
498 | else if (!mousedev->open++ && mousedev->exist) { | 573 | goto err_free_client; |
499 | error = input_open_device(&mousedev->handle); | ||
500 | if (error) | ||
501 | goto err_free_client; | ||
502 | } | ||
503 | 574 | ||
504 | file->private_data = client; | 575 | file->private_data = client; |
505 | return 0; | 576 | return 0; |
506 | 577 | ||
507 | err_free_client: | 578 | err_free_client: |
508 | list_del(&client->node); | 579 | mousedev_detach_client(mousedev, client); |
509 | kfree(client); | 580 | kfree(client); |
510 | err_put_mousedev: | 581 | err_put_mousedev: |
511 | put_device(&mousedev->dev); | 582 | put_device(&mousedev->dev); |
@@ -517,41 +588,41 @@ static inline int mousedev_limit_delta(int delta, int limit) | |||
517 | return delta > limit ? limit : (delta < -limit ? -limit : delta); | 588 | return delta > limit ? limit : (delta < -limit ? -limit : delta); |
518 | } | 589 | } |
519 | 590 | ||
520 | static void mousedev_packet(struct mousedev_client *client, signed char *ps2_data) | 591 | static void mousedev_packet(struct mousedev_client *client, |
592 | signed char *ps2_data) | ||
521 | { | 593 | { |
522 | struct mousedev_motion *p; | 594 | struct mousedev_motion *p = &client->packets[client->tail]; |
523 | unsigned long flags; | ||
524 | |||
525 | spin_lock_irqsave(&client->packet_lock, flags); | ||
526 | p = &client->packets[client->tail]; | ||
527 | 595 | ||
528 | ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07); | 596 | ps2_data[0] = 0x08 | |
597 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07); | ||
529 | ps2_data[1] = mousedev_limit_delta(p->dx, 127); | 598 | ps2_data[1] = mousedev_limit_delta(p->dx, 127); |
530 | ps2_data[2] = mousedev_limit_delta(p->dy, 127); | 599 | ps2_data[2] = mousedev_limit_delta(p->dy, 127); |
531 | p->dx -= ps2_data[1]; | 600 | p->dx -= ps2_data[1]; |
532 | p->dy -= ps2_data[2]; | 601 | p->dy -= ps2_data[2]; |
533 | 602 | ||
534 | switch (client->mode) { | 603 | switch (client->mode) { |
535 | case MOUSEDEV_EMUL_EXPS: | 604 | case MOUSEDEV_EMUL_EXPS: |
536 | ps2_data[3] = mousedev_limit_delta(p->dz, 7); | 605 | ps2_data[3] = mousedev_limit_delta(p->dz, 7); |
537 | p->dz -= ps2_data[3]; | 606 | p->dz -= ps2_data[3]; |
538 | ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1); | 607 | ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1); |
539 | client->bufsiz = 4; | 608 | client->bufsiz = 4; |
540 | break; | 609 | break; |
541 | 610 | ||
542 | case MOUSEDEV_EMUL_IMPS: | 611 | case MOUSEDEV_EMUL_IMPS: |
543 | ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); | 612 | ps2_data[0] |= |
544 | ps2_data[3] = mousedev_limit_delta(p->dz, 127); | 613 | ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); |
545 | p->dz -= ps2_data[3]; | 614 | ps2_data[3] = mousedev_limit_delta(p->dz, 127); |
546 | client->bufsiz = 4; | 615 | p->dz -= ps2_data[3]; |
547 | break; | 616 | client->bufsiz = 4; |
548 | 617 | break; | |
549 | case MOUSEDEV_EMUL_PS2: | 618 | |
550 | default: | 619 | case MOUSEDEV_EMUL_PS2: |
551 | ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); | 620 | default: |
552 | p->dz = 0; | 621 | ps2_data[0] |= |
553 | client->bufsiz = 3; | 622 | ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); |
554 | break; | 623 | p->dz = 0; |
624 | client->bufsiz = 3; | ||
625 | break; | ||
555 | } | 626 | } |
556 | 627 | ||
557 | if (!p->dx && !p->dy && !p->dz) { | 628 | if (!p->dx && !p->dy && !p->dz) { |
@@ -561,12 +632,56 @@ static void mousedev_packet(struct mousedev_client *client, signed char *ps2_dat | |||
561 | } else | 632 | } else |
562 | client->tail = (client->tail + 1) % PACKET_QUEUE_LEN; | 633 | client->tail = (client->tail + 1) % PACKET_QUEUE_LEN; |
563 | } | 634 | } |
564 | |||
565 | spin_unlock_irqrestore(&client->packet_lock, flags); | ||
566 | } | 635 | } |
567 | 636 | ||
637 | static void mousedev_generate_response(struct mousedev_client *client, | ||
638 | int command) | ||
639 | { | ||
640 | client->ps2[0] = 0xfa; /* ACK */ | ||
641 | |||
642 | switch (command) { | ||
568 | 643 | ||
569 | static ssize_t mousedev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 644 | case 0xeb: /* Poll */ |
645 | mousedev_packet(client, &client->ps2[1]); | ||
646 | client->bufsiz++; /* account for leading ACK */ | ||
647 | break; | ||
648 | |||
649 | case 0xf2: /* Get ID */ | ||
650 | switch (client->mode) { | ||
651 | case MOUSEDEV_EMUL_PS2: | ||
652 | client->ps2[1] = 0; | ||
653 | break; | ||
654 | case MOUSEDEV_EMUL_IMPS: | ||
655 | client->ps2[1] = 3; | ||
656 | break; | ||
657 | case MOUSEDEV_EMUL_EXPS: | ||
658 | client->ps2[1] = 4; | ||
659 | break; | ||
660 | } | ||
661 | client->bufsiz = 2; | ||
662 | break; | ||
663 | |||
664 | case 0xe9: /* Get info */ | ||
665 | client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200; | ||
666 | client->bufsiz = 4; | ||
667 | break; | ||
668 | |||
669 | case 0xff: /* Reset */ | ||
670 | client->impsseq = client->imexseq = 0; | ||
671 | client->mode = MOUSEDEV_EMUL_PS2; | ||
672 | client->ps2[1] = 0xaa; client->ps2[2] = 0x00; | ||
673 | client->bufsiz = 3; | ||
674 | break; | ||
675 | |||
676 | default: | ||
677 | client->bufsiz = 1; | ||
678 | break; | ||
679 | } | ||
680 | client->buffer = client->bufsiz; | ||
681 | } | ||
682 | |||
683 | static ssize_t mousedev_write(struct file *file, const char __user *buffer, | ||
684 | size_t count, loff_t *ppos) | ||
570 | { | 685 | { |
571 | struct mousedev_client *client = file->private_data; | 686 | struct mousedev_client *client = file->private_data; |
572 | unsigned char c; | 687 | unsigned char c; |
@@ -577,6 +692,8 @@ static ssize_t mousedev_write(struct file *file, const char __user *buffer, size | |||
577 | if (get_user(c, buffer + i)) | 692 | if (get_user(c, buffer + i)) |
578 | return -EFAULT; | 693 | return -EFAULT; |
579 | 694 | ||
695 | spin_lock_irq(&client->packet_lock); | ||
696 | |||
580 | if (c == mousedev_imex_seq[client->imexseq]) { | 697 | if (c == mousedev_imex_seq[client->imexseq]) { |
581 | if (++client->imexseq == MOUSEDEV_SEQ_LEN) { | 698 | if (++client->imexseq == MOUSEDEV_SEQ_LEN) { |
582 | client->imexseq = 0; | 699 | client->imexseq = 0; |
@@ -593,68 +710,39 @@ static ssize_t mousedev_write(struct file *file, const char __user *buffer, size | |||
593 | } else | 710 | } else |
594 | client->impsseq = 0; | 711 | client->impsseq = 0; |
595 | 712 | ||
596 | client->ps2[0] = 0xfa; | 713 | mousedev_generate_response(client, c); |
597 | |||
598 | switch (c) { | ||
599 | |||
600 | case 0xeb: /* Poll */ | ||
601 | mousedev_packet(client, &client->ps2[1]); | ||
602 | client->bufsiz++; /* account for leading ACK */ | ||
603 | break; | ||
604 | |||
605 | case 0xf2: /* Get ID */ | ||
606 | switch (client->mode) { | ||
607 | case MOUSEDEV_EMUL_PS2: client->ps2[1] = 0; break; | ||
608 | case MOUSEDEV_EMUL_IMPS: client->ps2[1] = 3; break; | ||
609 | case MOUSEDEV_EMUL_EXPS: client->ps2[1] = 4; break; | ||
610 | } | ||
611 | client->bufsiz = 2; | ||
612 | break; | ||
613 | |||
614 | case 0xe9: /* Get info */ | ||
615 | client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200; | ||
616 | client->bufsiz = 4; | ||
617 | break; | ||
618 | |||
619 | case 0xff: /* Reset */ | ||
620 | client->impsseq = client->imexseq = 0; | ||
621 | client->mode = MOUSEDEV_EMUL_PS2; | ||
622 | client->ps2[1] = 0xaa; client->ps2[2] = 0x00; | ||
623 | client->bufsiz = 3; | ||
624 | break; | ||
625 | |||
626 | default: | ||
627 | client->bufsiz = 1; | ||
628 | break; | ||
629 | } | ||
630 | 714 | ||
631 | client->buffer = client->bufsiz; | 715 | spin_unlock_irq(&client->packet_lock); |
632 | } | 716 | } |
633 | 717 | ||
634 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | 718 | kill_fasync(&client->fasync, SIGIO, POLL_IN); |
635 | |||
636 | wake_up_interruptible(&client->mousedev->wait); | 719 | wake_up_interruptible(&client->mousedev->wait); |
637 | 720 | ||
638 | return count; | 721 | return count; |
639 | } | 722 | } |
640 | 723 | ||
641 | static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 724 | static ssize_t mousedev_read(struct file *file, char __user *buffer, |
725 | size_t count, loff_t *ppos) | ||
642 | { | 726 | { |
643 | struct mousedev_client *client = file->private_data; | 727 | struct mousedev_client *client = file->private_data; |
728 | struct mousedev *mousedev = client->mousedev; | ||
729 | signed char data[sizeof(client->ps2)]; | ||
644 | int retval = 0; | 730 | int retval = 0; |
645 | 731 | ||
646 | if (!client->ready && !client->buffer && (file->f_flags & O_NONBLOCK)) | 732 | if (!client->ready && !client->buffer && mousedev->exist && |
733 | (file->f_flags & O_NONBLOCK)) | ||
647 | return -EAGAIN; | 734 | return -EAGAIN; |
648 | 735 | ||
649 | retval = wait_event_interruptible(client->mousedev->wait, | 736 | retval = wait_event_interruptible(mousedev->wait, |
650 | !client->mousedev->exist || client->ready || client->buffer); | 737 | !mousedev->exist || client->ready || client->buffer); |
651 | |||
652 | if (retval) | 738 | if (retval) |
653 | return retval; | 739 | return retval; |
654 | 740 | ||
655 | if (!client->mousedev->exist) | 741 | if (!mousedev->exist) |
656 | return -ENODEV; | 742 | return -ENODEV; |
657 | 743 | ||
744 | spin_lock_irq(&client->packet_lock); | ||
745 | |||
658 | if (!client->buffer && client->ready) { | 746 | if (!client->buffer && client->ready) { |
659 | mousedev_packet(client, client->ps2); | 747 | mousedev_packet(client, client->ps2); |
660 | client->buffer = client->bufsiz; | 748 | client->buffer = client->bufsiz; |
@@ -663,9 +751,12 @@ static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t coun | |||
663 | if (count > client->buffer) | 751 | if (count > client->buffer) |
664 | count = client->buffer; | 752 | count = client->buffer; |
665 | 753 | ||
754 | memcpy(data, client->ps2 + client->bufsiz - client->buffer, count); | ||
666 | client->buffer -= count; | 755 | client->buffer -= count; |
667 | 756 | ||
668 | if (copy_to_user(buffer, client->ps2 + client->bufsiz - client->buffer - count, count)) | 757 | spin_unlock_irq(&client->packet_lock); |
758 | |||
759 | if (copy_to_user(buffer, data, count)) | ||
669 | return -EFAULT; | 760 | return -EFAULT; |
670 | 761 | ||
671 | return count; | 762 | return count; |
@@ -692,6 +783,60 @@ static const struct file_operations mousedev_fops = { | |||
692 | .fasync = mousedev_fasync, | 783 | .fasync = mousedev_fasync, |
693 | }; | 784 | }; |
694 | 785 | ||
786 | static int mousedev_install_chrdev(struct mousedev *mousedev) | ||
787 | { | ||
788 | mousedev_table[mousedev->minor] = mousedev; | ||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static void mousedev_remove_chrdev(struct mousedev *mousedev) | ||
793 | { | ||
794 | mutex_lock(&mousedev_table_mutex); | ||
795 | mousedev_table[mousedev->minor] = NULL; | ||
796 | mutex_unlock(&mousedev_table_mutex); | ||
797 | } | ||
798 | |||
799 | /* | ||
800 | * Mark device non-existent. This disables writes, ioctls and | ||
801 | * prevents new users from opening the device. Already posted | ||
802 | * blocking reads will stay, however new ones will fail. | ||
803 | */ | ||
804 | static void mousedev_mark_dead(struct mousedev *mousedev) | ||
805 | { | ||
806 | mutex_lock(&mousedev->mutex); | ||
807 | mousedev->exist = 0; | ||
808 | mutex_unlock(&mousedev->mutex); | ||
809 | } | ||
810 | |||
811 | /* | ||
812 | * Wake up users waiting for IO so they can disconnect from | ||
813 | * dead device. | ||
814 | */ | ||
815 | static void mousedev_hangup(struct mousedev *mousedev) | ||
816 | { | ||
817 | struct mousedev_client *client; | ||
818 | |||
819 | spin_lock(&mousedev->client_lock); | ||
820 | list_for_each_entry(client, &mousedev->client_list, node) | ||
821 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
822 | spin_unlock(&mousedev->client_lock); | ||
823 | |||
824 | wake_up_interruptible(&mousedev->wait); | ||
825 | } | ||
826 | |||
827 | static void mousedev_cleanup(struct mousedev *mousedev) | ||
828 | { | ||
829 | struct input_handle *handle = &mousedev->handle; | ||
830 | |||
831 | mousedev_mark_dead(mousedev); | ||
832 | mousedev_hangup(mousedev); | ||
833 | mousedev_remove_chrdev(mousedev); | ||
834 | |||
835 | /* mousedev is marked dead so no one else accesses mousedev->open */ | ||
836 | if (mousedev->open) | ||
837 | input_close_device(handle); | ||
838 | } | ||
839 | |||
695 | static struct mousedev *mousedev_create(struct input_dev *dev, | 840 | static struct mousedev *mousedev_create(struct input_dev *dev, |
696 | struct input_handler *handler, | 841 | struct input_handler *handler, |
697 | int minor) | 842 | int minor) |
@@ -707,6 +852,10 @@ static struct mousedev *mousedev_create(struct input_dev *dev, | |||
707 | 852 | ||
708 | INIT_LIST_HEAD(&mousedev->client_list); | 853 | INIT_LIST_HEAD(&mousedev->client_list); |
709 | INIT_LIST_HEAD(&mousedev->mixdev_node); | 854 | INIT_LIST_HEAD(&mousedev->mixdev_node); |
855 | spin_lock_init(&mousedev->client_lock); | ||
856 | mutex_init(&mousedev->mutex); | ||
857 | lockdep_set_subclass(&mousedev->mutex, | ||
858 | minor == MOUSEDEV_MIX ? MOUSEDEV_MIX : 0); | ||
710 | init_waitqueue_head(&mousedev->wait); | 859 | init_waitqueue_head(&mousedev->wait); |
711 | 860 | ||
712 | if (minor == MOUSEDEV_MIX) | 861 | if (minor == MOUSEDEV_MIX) |
@@ -731,14 +880,27 @@ static struct mousedev *mousedev_create(struct input_dev *dev, | |||
731 | mousedev->dev.release = mousedev_free; | 880 | mousedev->dev.release = mousedev_free; |
732 | device_initialize(&mousedev->dev); | 881 | device_initialize(&mousedev->dev); |
733 | 882 | ||
734 | mousedev_table[minor] = mousedev; | 883 | if (minor != MOUSEDEV_MIX) { |
884 | error = input_register_handle(&mousedev->handle); | ||
885 | if (error) | ||
886 | goto err_free_mousedev; | ||
887 | } | ||
888 | |||
889 | error = mousedev_install_chrdev(mousedev); | ||
890 | if (error) | ||
891 | goto err_unregister_handle; | ||
735 | 892 | ||
736 | error = device_add(&mousedev->dev); | 893 | error = device_add(&mousedev->dev); |
737 | if (error) | 894 | if (error) |
738 | goto err_free_mousedev; | 895 | goto err_cleanup_mousedev; |
739 | 896 | ||
740 | return mousedev; | 897 | return mousedev; |
741 | 898 | ||
899 | err_cleanup_mousedev: | ||
900 | mousedev_cleanup(mousedev); | ||
901 | err_unregister_handle: | ||
902 | if (minor != MOUSEDEV_MIX) | ||
903 | input_unregister_handle(&mousedev->handle); | ||
742 | err_free_mousedev: | 904 | err_free_mousedev: |
743 | put_device(&mousedev->dev); | 905 | put_device(&mousedev->dev); |
744 | err_out: | 906 | err_out: |
@@ -747,29 +909,64 @@ static struct mousedev *mousedev_create(struct input_dev *dev, | |||
747 | 909 | ||
748 | static void mousedev_destroy(struct mousedev *mousedev) | 910 | static void mousedev_destroy(struct mousedev *mousedev) |
749 | { | 911 | { |
750 | struct mousedev_client *client; | ||
751 | |||
752 | device_del(&mousedev->dev); | 912 | device_del(&mousedev->dev); |
753 | mousedev->exist = 0; | 913 | mousedev_cleanup(mousedev); |
914 | if (mousedev->minor != MOUSEDEV_MIX) | ||
915 | input_unregister_handle(&mousedev->handle); | ||
916 | put_device(&mousedev->dev); | ||
917 | } | ||
754 | 918 | ||
755 | if (mousedev->open) { | 919 | static int mixdev_add_device(struct mousedev *mousedev) |
756 | input_close_device(&mousedev->handle); | 920 | { |
757 | list_for_each_entry(client, &mousedev->client_list, node) | 921 | int retval; |
758 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | 922 | |
759 | wake_up_interruptible(&mousedev->wait); | 923 | retval = mutex_lock_interruptible(&mousedev_mix->mutex); |
924 | if (retval) | ||
925 | return retval; | ||
926 | |||
927 | if (mousedev_mix->open) { | ||
928 | retval = mousedev_open_device(mousedev); | ||
929 | if (retval) | ||
930 | goto out; | ||
931 | |||
932 | mousedev->mixdev_open = 1; | ||
760 | } | 933 | } |
761 | 934 | ||
935 | get_device(&mousedev->dev); | ||
936 | list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list); | ||
937 | |||
938 | out: | ||
939 | mutex_unlock(&mousedev_mix->mutex); | ||
940 | return retval; | ||
941 | } | ||
942 | |||
943 | static void mixdev_remove_device(struct mousedev *mousedev) | ||
944 | { | ||
945 | mutex_lock(&mousedev_mix->mutex); | ||
946 | |||
947 | if (mousedev->mixdev_open) { | ||
948 | mousedev->mixdev_open = 0; | ||
949 | mousedev_close_device(mousedev); | ||
950 | } | ||
951 | |||
952 | list_del_init(&mousedev->mixdev_node); | ||
953 | mutex_unlock(&mousedev_mix->mutex); | ||
954 | |||
762 | put_device(&mousedev->dev); | 955 | put_device(&mousedev->dev); |
763 | } | 956 | } |
764 | 957 | ||
765 | static int mousedev_connect(struct input_handler *handler, struct input_dev *dev, | 958 | static int mousedev_connect(struct input_handler *handler, |
959 | struct input_dev *dev, | ||
766 | const struct input_device_id *id) | 960 | const struct input_device_id *id) |
767 | { | 961 | { |
768 | struct mousedev *mousedev; | 962 | struct mousedev *mousedev; |
769 | int minor; | 963 | int minor; |
770 | int error; | 964 | int error; |
771 | 965 | ||
772 | for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); | 966 | for (minor = 0; minor < MOUSEDEV_MINORS; minor++) |
967 | if (!mousedev_table[minor]) | ||
968 | break; | ||
969 | |||
773 | if (minor == MOUSEDEV_MINORS) { | 970 | if (minor == MOUSEDEV_MINORS) { |
774 | printk(KERN_ERR "mousedev: no more free mousedev devices\n"); | 971 | printk(KERN_ERR "mousedev: no more free mousedev devices\n"); |
775 | return -ENFILE; | 972 | return -ENFILE; |
@@ -779,21 +976,13 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev | |||
779 | if (IS_ERR(mousedev)) | 976 | if (IS_ERR(mousedev)) |
780 | return PTR_ERR(mousedev); | 977 | return PTR_ERR(mousedev); |
781 | 978 | ||
782 | error = input_register_handle(&mousedev->handle); | ||
783 | if (error) | ||
784 | goto err_delete_mousedev; | ||
785 | |||
786 | error = mixdev_add_device(mousedev); | 979 | error = mixdev_add_device(mousedev); |
787 | if (error) | 980 | if (error) { |
788 | goto err_unregister_handle; | 981 | mousedev_destroy(mousedev); |
982 | return error; | ||
983 | } | ||
789 | 984 | ||
790 | return 0; | 985 | return 0; |
791 | |||
792 | err_unregister_handle: | ||
793 | input_unregister_handle(&mousedev->handle); | ||
794 | err_delete_mousedev: | ||
795 | device_unregister(&mousedev->dev); | ||
796 | return error; | ||
797 | } | 986 | } |
798 | 987 | ||
799 | static void mousedev_disconnect(struct input_handle *handle) | 988 | static void mousedev_disconnect(struct input_handle *handle) |
@@ -801,33 +990,42 @@ static void mousedev_disconnect(struct input_handle *handle) | |||
801 | struct mousedev *mousedev = handle->private; | 990 | struct mousedev *mousedev = handle->private; |
802 | 991 | ||
803 | mixdev_remove_device(mousedev); | 992 | mixdev_remove_device(mousedev); |
804 | input_unregister_handle(handle); | ||
805 | mousedev_destroy(mousedev); | 993 | mousedev_destroy(mousedev); |
806 | } | 994 | } |
807 | 995 | ||
808 | static const struct input_device_id mousedev_ids[] = { | 996 | static const struct input_device_id mousedev_ids[] = { |
809 | { | 997 | { |
810 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, | 998 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
999 | INPUT_DEVICE_ID_MATCH_KEYBIT | | ||
1000 | INPUT_DEVICE_ID_MATCH_RELBIT, | ||
811 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, | 1001 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, |
812 | .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, | 1002 | .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, |
813 | .relbit = { BIT(REL_X) | BIT(REL_Y) }, | 1003 | .relbit = { BIT(REL_X) | BIT(REL_Y) }, |
814 | }, /* A mouse like device, at least one button, two relative axes */ | 1004 | }, /* A mouse like device, at least one button, |
1005 | two relative axes */ | ||
815 | { | 1006 | { |
816 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_RELBIT, | 1007 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
1008 | INPUT_DEVICE_ID_MATCH_RELBIT, | ||
817 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, | 1009 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, |
818 | .relbit = { BIT(REL_WHEEL) }, | 1010 | .relbit = { BIT(REL_WHEEL) }, |
819 | }, /* A separate scrollwheel */ | 1011 | }, /* A separate scrollwheel */ |
820 | { | 1012 | { |
821 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | 1013 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
1014 | INPUT_DEVICE_ID_MATCH_KEYBIT | | ||
1015 | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
822 | .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, | 1016 | .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, |
823 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, | 1017 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, |
824 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, | 1018 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, |
825 | }, /* A tablet like device, at least touch detection, two absolute axes */ | 1019 | }, /* A tablet like device, at least touch detection, |
1020 | two absolute axes */ | ||
826 | { | 1021 | { |
827 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | 1022 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
1023 | INPUT_DEVICE_ID_MATCH_KEYBIT | | ||
1024 | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
828 | .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, | 1025 | .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, |
829 | .keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) }, | 1026 | .keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) }, |
830 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) }, | 1027 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | |
1028 | BIT(ABS_TOOL_WIDTH) }, | ||
831 | }, /* A touchpad */ | 1029 | }, /* A touchpad */ |
832 | 1030 | ||
833 | { }, /* Terminating entry */ | 1031 | { }, /* Terminating entry */ |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index c2eea2767e10..11dafc0ee994 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -385,6 +385,8 @@ static int i8042_enable_kbd_port(void) | |||
385 | i8042_ctr |= I8042_CTR_KBDINT; | 385 | i8042_ctr |= I8042_CTR_KBDINT; |
386 | 386 | ||
387 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 387 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
388 | i8042_ctr &= ~I8042_CTR_KBDINT; | ||
389 | i8042_ctr |= I8042_CTR_KBDDIS; | ||
388 | printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); | 390 | printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); |
389 | return -EIO; | 391 | return -EIO; |
390 | } | 392 | } |
@@ -402,6 +404,8 @@ static int i8042_enable_aux_port(void) | |||
402 | i8042_ctr |= I8042_CTR_AUXINT; | 404 | i8042_ctr |= I8042_CTR_AUXINT; |
403 | 405 | ||
404 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 406 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
407 | i8042_ctr &= ~I8042_CTR_AUXINT; | ||
408 | i8042_ctr |= I8042_CTR_AUXDIS; | ||
405 | printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); | 409 | printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); |
406 | return -EIO; | 410 | return -EIO; |
407 | } | 411 | } |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index f929fcdbae2e..e3e0baa1a158 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -126,6 +126,16 @@ config TOUCHSCREEN_HP600 | |||
126 | To compile this driver as a module, choose M here: the | 126 | To compile this driver as a module, choose M here: the |
127 | module will be called hp680_ts_input. | 127 | module will be called hp680_ts_input. |
128 | 128 | ||
129 | config TOUCHSCREEN_HP7XX | ||
130 | tristate "HP Jornada 710/720/728 touchscreen" | ||
131 | depends on SA1100_JORNADA720_SSP | ||
132 | help | ||
133 | Say Y here if you have a HP Jornada 710/720/728 and want | ||
134 | to support the built-in touchscreen. | ||
135 | |||
136 | To compile this driver as a module, choose M here: the | ||
137 | module will be called jornada720_ts. | ||
138 | |||
129 | config TOUCHSCREEN_PENMOUNT | 139 | config TOUCHSCREEN_PENMOUNT |
130 | tristate "Penmount serial touchscreen" | 140 | tristate "Penmount serial touchscreen" |
131 | select SERIO | 141 | select SERIO |
@@ -191,6 +201,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
191 | - Gunze AHL61 | 201 | - Gunze AHL61 |
192 | - DMC TSC-10/25 | 202 | - DMC TSC-10/25 |
193 | - IRTOUCHSYSTEMS/UNITOP | 203 | - IRTOUCHSYSTEMS/UNITOP |
204 | - IdealTEK URTC1000 | ||
194 | 205 | ||
195 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 206 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
196 | a usage description and the required user-space stuff. | 207 | a usage description and the required user-space stuff. |
@@ -238,4 +249,14 @@ config TOUCHSCREEN_USB_IRTOUCH | |||
238 | bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED | 249 | bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED |
239 | depends on TOUCHSCREEN_USB_COMPOSITE | 250 | depends on TOUCHSCREEN_USB_COMPOSITE |
240 | 251 | ||
252 | config TOUCHSCREEN_USB_IDEALTEK | ||
253 | default y | ||
254 | bool "IdealTEK URTC1000 device support" if EMBEDDED | ||
255 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
256 | |||
257 | config TOUCHSCREEN_USB_GENERAL_TOUCH | ||
258 | default y | ||
259 | bool "GeneralTouch Touchscreen device support" if EMBEDDED | ||
260 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
261 | |||
241 | endif | 262 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 5de8933c4993..35d4097df35a 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | |||
13 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o | 13 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o |
14 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o | 14 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o |
15 | obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o | 15 | obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o |
16 | obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o | ||
16 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o | 17 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o |
17 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 18 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
18 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 19 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c new file mode 100644 index 000000000000..42a1c9a1940e --- /dev/null +++ b/drivers/input/touchscreen/jornada720_ts.c | |||
@@ -0,0 +1,182 @@ | |||
1 | /* | ||
2 | * drivers/input/touchscreen/jornada720_ts.c | ||
3 | * | ||
4 | * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com> | ||
5 | * | ||
6 | * Copyright (C) 2006 Filip Zyzniewski <filip.zyzniewski@tefnet.pl> | ||
7 | * based on HP Jornada 56x touchscreen driver by Alex Lange <chicken@handhelds.org> | ||
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 version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * HP Jornada 710/720/729 Touchscreen Driver | ||
14 | */ | ||
15 | |||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/module.h> | ||
21 | |||
22 | #include <asm/hardware.h> | ||
23 | #include <asm/arch/jornada720.h> | ||
24 | |||
25 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); | ||
26 | MODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver"); | ||
27 | MODULE_LICENSE("GPLv2"); | ||
28 | |||
29 | struct jornada_ts { | ||
30 | struct input_dev *dev; | ||
31 | int x_data[4]; /* X sample values */ | ||
32 | int y_data[4]; /* Y sample values */ | ||
33 | }; | ||
34 | |||
35 | static void jornada720_ts_collect_data(struct jornada_ts *jornada_ts) | ||
36 | { | ||
37 | |||
38 | /* 3 low word X samples */ | ||
39 | jornada_ts->x_data[0] = jornada_ssp_byte(TXDUMMY); | ||
40 | jornada_ts->x_data[1] = jornada_ssp_byte(TXDUMMY); | ||
41 | jornada_ts->x_data[2] = jornada_ssp_byte(TXDUMMY); | ||
42 | |||
43 | /* 3 low word Y samples */ | ||
44 | jornada_ts->y_data[0] = jornada_ssp_byte(TXDUMMY); | ||
45 | jornada_ts->y_data[1] = jornada_ssp_byte(TXDUMMY); | ||
46 | jornada_ts->y_data[2] = jornada_ssp_byte(TXDUMMY); | ||
47 | |||
48 | /* combined x samples bits */ | ||
49 | jornada_ts->x_data[3] = jornada_ssp_byte(TXDUMMY); | ||
50 | |||
51 | /* combined y samples bits */ | ||
52 | jornada_ts->y_data[3] = jornada_ssp_byte(TXDUMMY); | ||
53 | } | ||
54 | |||
55 | static int jornada720_ts_average(int coords[4]) | ||
56 | { | ||
57 | int coord, high_bits = coords[3]; | ||
58 | |||
59 | coord = coords[0] | ((high_bits & 0x03) << 8); | ||
60 | coord += coords[1] | ((high_bits & 0x0c) << 6); | ||
61 | coord += coords[2] | ((high_bits & 0x30) << 4); | ||
62 | |||
63 | return coord / 3; | ||
64 | } | ||
65 | |||
66 | static irqreturn_t jornada720_ts_interrupt(int irq, void *dev_id) | ||
67 | { | ||
68 | struct platform_device *pdev = dev_id; | ||
69 | struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); | ||
70 | struct input_dev *input = jornada_ts->dev; | ||
71 | int x, y; | ||
72 | |||
73 | /* If GPIO_GPIO9 is set to high then report pen up */ | ||
74 | if (GPLR & GPIO_GPIO(9)) { | ||
75 | input_report_key(input, BTN_TOUCH, 0); | ||
76 | input_sync(input); | ||
77 | } else { | ||
78 | jornada_ssp_start(); | ||
79 | |||
80 | /* proper reply to request is always TXDUMMY */ | ||
81 | if (jornada_ssp_inout(GETTOUCHSAMPLES) == TXDUMMY) { | ||
82 | jornada720_ts_collect_data(jornada_ts); | ||
83 | |||
84 | x = jornada720_ts_average(jornada_ts->x_data); | ||
85 | y = jornada720_ts_average(jornada_ts->y_data); | ||
86 | |||
87 | input_report_key(input, BTN_TOUCH, 1); | ||
88 | input_report_abs(input, ABS_X, x); | ||
89 | input_report_abs(input, ABS_Y, y); | ||
90 | input_sync(input); | ||
91 | } | ||
92 | |||
93 | jornada_ssp_end(); | ||
94 | } | ||
95 | |||
96 | return IRQ_HANDLED; | ||
97 | } | ||
98 | |||
99 | static int __devinit jornada720_ts_probe(struct platform_device *pdev) | ||
100 | { | ||
101 | struct jornada_ts *jornada_ts; | ||
102 | struct input_dev *input_dev; | ||
103 | int error; | ||
104 | |||
105 | jornada_ts = kzalloc(sizeof(struct jornada_ts), GFP_KERNEL); | ||
106 | input_dev = input_allocate_device(); | ||
107 | |||
108 | if (!jornada_ts || !input_dev) { | ||
109 | error = -ENOMEM; | ||
110 | goto fail1; | ||
111 | } | ||
112 | |||
113 | platform_set_drvdata(pdev, jornada_ts); | ||
114 | |||
115 | jornada_ts->dev = input_dev; | ||
116 | |||
117 | input_dev->name = "HP Jornada 7xx Touchscreen"; | ||
118 | input_dev->phys = "jornadats/input0"; | ||
119 | input_dev->id.bustype = BUS_HOST; | ||
120 | input_dev->dev.parent = &pdev->dev; | ||
121 | |||
122 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
123 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
124 | input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0); | ||
125 | input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0); | ||
126 | |||
127 | error = request_irq(IRQ_GPIO9, | ||
128 | jornada720_ts_interrupt, | ||
129 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | ||
130 | "HP7XX Touchscreen driver", pdev); | ||
131 | if (error) { | ||
132 | printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n"); | ||
133 | goto fail1; | ||
134 | } | ||
135 | |||
136 | error = input_register_device(jornada_ts->dev); | ||
137 | if (error) | ||
138 | goto fail2; | ||
139 | |||
140 | return 0; | ||
141 | |||
142 | fail2: | ||
143 | free_irq(IRQ_GPIO9, pdev); | ||
144 | fail1: | ||
145 | platform_set_drvdata(pdev, NULL); | ||
146 | input_free_device(input_dev); | ||
147 | kfree(jornada_ts); | ||
148 | return error; | ||
149 | } | ||
150 | |||
151 | static int __devexit jornada720_ts_remove(struct platform_device *pdev) | ||
152 | { | ||
153 | struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); | ||
154 | |||
155 | free_irq(IRQ_GPIO9, pdev); | ||
156 | platform_set_drvdata(pdev, NULL); | ||
157 | input_unregister_device(jornada_ts->dev); | ||
158 | kfree(jornada_ts); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static struct platform_driver jornada720_ts_driver = { | ||
164 | .probe = jornada720_ts_probe, | ||
165 | .remove = __devexit_p(jornada720_ts_remove), | ||
166 | .driver = { | ||
167 | .name = "jornada_ts", | ||
168 | }, | ||
169 | }; | ||
170 | |||
171 | static int __init jornada720_ts_init(void) | ||
172 | { | ||
173 | return platform_driver_register(&jornada720_ts_driver); | ||
174 | } | ||
175 | |||
176 | static void __exit jornada720_ts_exit(void) | ||
177 | { | ||
178 | platform_driver_unregister(&jornada720_ts_driver); | ||
179 | } | ||
180 | |||
181 | module_init(jornada720_ts_init); | ||
182 | module_exit(jornada720_ts_exit); | ||
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 36f944019158..86aed64ec0fb 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
@@ -130,8 +130,7 @@ static unsigned int ucb1400_adc_read(struct ucb1400 *ucb, u16 adc_channel) | |||
130 | if (val & UCB_ADC_DAT_VALID) | 130 | if (val & UCB_ADC_DAT_VALID) |
131 | break; | 131 | break; |
132 | /* yield to other processes */ | 132 | /* yield to other processes */ |
133 | set_current_state(TASK_INTERRUPTIBLE); | 133 | schedule_timeout_uninterruptible(1); |
134 | schedule_timeout(1); | ||
135 | } | 134 | } |
136 | 135 | ||
137 | return UCB_ADC_DAT_VALUE(val); | 136 | return UCB_ADC_DAT_VALUE(val); |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 741f6c6f1e50..9fb3d5c30999 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * - Gunze AHL61 | 10 | * - Gunze AHL61 |
11 | * - DMC TSC-10/25 | 11 | * - DMC TSC-10/25 |
12 | * - IRTOUCHSYSTEMS/UNITOP | 12 | * - IRTOUCHSYSTEMS/UNITOP |
13 | * - IdealTEK URTC1000 | ||
13 | * | 14 | * |
14 | * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> | 15 | * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> |
15 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 16 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
@@ -92,7 +93,7 @@ struct usbtouch_usb { | |||
92 | }; | 93 | }; |
93 | 94 | ||
94 | 95 | ||
95 | #if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO) | 96 | #if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO) || defined(CONFIG_TOUCHSCREEN_USB_IDEALTEK) |
96 | #define MULTI_PACKET | 97 | #define MULTI_PACKET |
97 | #endif | 98 | #endif |
98 | 99 | ||
@@ -112,6 +113,8 @@ enum { | |||
112 | DEVTYPE_GUNZE, | 113 | DEVTYPE_GUNZE, |
113 | DEVTYPE_DMC_TSC10, | 114 | DEVTYPE_DMC_TSC10, |
114 | DEVTYPE_IRTOUCH, | 115 | DEVTYPE_IRTOUCH, |
116 | DEVTYPE_IDEALTEK, | ||
117 | DEVTYPE_GENERAL_TOUCH, | ||
115 | }; | 118 | }; |
116 | 119 | ||
117 | static struct usb_device_id usbtouch_devices[] = { | 120 | static struct usb_device_id usbtouch_devices[] = { |
@@ -157,6 +160,14 @@ static struct usb_device_id usbtouch_devices[] = { | |||
157 | {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | 160 | {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, |
158 | #endif | 161 | #endif |
159 | 162 | ||
163 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | ||
164 | {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, | ||
165 | #endif | ||
166 | |||
167 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | ||
168 | {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, | ||
169 | #endif | ||
170 | |||
160 | {} | 171 | {} |
161 | }; | 172 | }; |
162 | 173 | ||
@@ -396,7 +407,8 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) | |||
396 | TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); | 407 | TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); |
397 | if (ret < 0) | 408 | if (ret < 0) |
398 | return ret; | 409 | return ret; |
399 | if (buf[0] != 0x06 || buf[1] != 0x00) | 410 | if ((buf[0] != 0x06 || buf[1] != 0x00) && |
411 | (buf[0] != 0x15 || buf[1] != 0x01)) | ||
400 | return -ENODEV; | 412 | return -ENODEV; |
401 | 413 | ||
402 | /* start sending data */ | 414 | /* start sending data */ |
@@ -438,6 +450,57 @@ static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
438 | 450 | ||
439 | 451 | ||
440 | /***************************************************************************** | 452 | /***************************************************************************** |
453 | * IdealTEK URTC1000 Part | ||
454 | */ | ||
455 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | ||
456 | static int idealtek_get_pkt_len(unsigned char *buf, int len) | ||
457 | { | ||
458 | if (buf[0] & 0x80) | ||
459 | return 5; | ||
460 | if (buf[0] == 0x01) | ||
461 | return len; | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
466 | { | ||
467 | switch (pkt[0] & 0x98) { | ||
468 | case 0x88: | ||
469 | /* touch data in IdealTEK mode */ | ||
470 | dev->x = (pkt[1] << 5) | (pkt[2] >> 2); | ||
471 | dev->y = (pkt[3] << 5) | (pkt[4] >> 2); | ||
472 | dev->touch = (pkt[0] & 0x40) ? 1 : 0; | ||
473 | return 1; | ||
474 | |||
475 | case 0x98: | ||
476 | /* touch data in MT emulation mode */ | ||
477 | dev->x = (pkt[2] << 5) | (pkt[1] >> 2); | ||
478 | dev->y = (pkt[4] << 5) | (pkt[3] >> 2); | ||
479 | dev->touch = (pkt[0] & 0x40) ? 1 : 0; | ||
480 | return 1; | ||
481 | |||
482 | default: | ||
483 | return 0; | ||
484 | } | ||
485 | } | ||
486 | #endif | ||
487 | |||
488 | /***************************************************************************** | ||
489 | * General Touch Part | ||
490 | */ | ||
491 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | ||
492 | static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
493 | { | ||
494 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1] ; | ||
495 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3] ; | ||
496 | dev->press = pkt[5] & 0xff; | ||
497 | dev->touch = pkt[0] & 0x01; | ||
498 | |||
499 | return 1; | ||
500 | } | ||
501 | #endif | ||
502 | |||
503 | /***************************************************************************** | ||
441 | * the different device descriptors | 504 | * the different device descriptors |
442 | */ | 505 | */ |
443 | static struct usbtouch_device_info usbtouch_dev_info[] = { | 506 | static struct usbtouch_device_info usbtouch_dev_info[] = { |
@@ -537,6 +600,32 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
537 | .read_data = irtouch_read_data, | 600 | .read_data = irtouch_read_data, |
538 | }, | 601 | }, |
539 | #endif | 602 | #endif |
603 | |||
604 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | ||
605 | [DEVTYPE_IDEALTEK] = { | ||
606 | .min_xc = 0x0, | ||
607 | .max_xc = 0x0fff, | ||
608 | .min_yc = 0x0, | ||
609 | .max_yc = 0x0fff, | ||
610 | .rept_size = 8, | ||
611 | .flags = USBTOUCH_FLG_BUFFER, | ||
612 | .process_pkt = usbtouch_process_multi, | ||
613 | .get_pkt_len = idealtek_get_pkt_len, | ||
614 | .read_data = idealtek_read_data, | ||
615 | }, | ||
616 | #endif | ||
617 | |||
618 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | ||
619 | [DEVTYPE_GENERAL_TOUCH] = { | ||
620 | .min_xc = 0x0, | ||
621 | .max_xc = 0x0500, | ||
622 | .min_yc = 0x0, | ||
623 | .max_yc = 0x0500, | ||
624 | .rept_size = 7, | ||
625 | .read_data = general_touch_read_data, | ||
626 | } | ||
627 | #endif | ||
628 | |||
540 | }; | 629 | }; |
541 | 630 | ||
542 | 631 | ||
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c deleted file mode 100644 index d2f882e98e5e..000000000000 --- a/drivers/input/tsdev.c +++ /dev/null | |||
@@ -1,533 +0,0 @@ | |||
1 | /* | ||
2 | * $Id: tsdev.c,v 1.15 2002/04/10 16:50:19 jsimmons Exp $ | ||
3 | * | ||
4 | * Copyright (c) 2001 "Crazy" james Simmons | ||
5 | * | ||
6 | * Compaq touchscreen protocol driver. The protocol emulated by this driver | ||
7 | * is obsolete; for new programs use the tslib library which can read directly | ||
8 | * from evdev and perform dejittering, variance filtering and calibration - | ||
9 | * all in user space, not at kernel level. The meaning of this driver is | ||
10 | * to allow usage of newer input drivers with old applications that use the | ||
11 | * old /dev/h3600_ts and /dev/h3600_tsraw devices. | ||
12 | * | ||
13 | * 09-Apr-2004: Andrew Zabolotny <zap@homelink.ru> | ||
14 | * Fixed to actually work, not just output random numbers. | ||
15 | * Added support for both h3600_ts and h3600_tsraw protocol | ||
16 | * emulation. | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * This program is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation; either version 2 of the License, or | ||
23 | * (at your option) any later version. | ||
24 | * | ||
25 | * This program is distributed in the hope that it will be useful, | ||
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
28 | * GNU General Public License for more details. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License | ||
31 | * along with this program; if not, write to the Free Software | ||
32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
33 | * | ||
34 | * Should you need to contact me, the author, you can do so either by | ||
35 | * e-mail - mail your message to <jsimmons@infradead.org>. | ||
36 | */ | ||
37 | |||
38 | #define TSDEV_MINOR_BASE 128 | ||
39 | #define TSDEV_MINORS 32 | ||
40 | /* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */ | ||
41 | #define TSDEV_MINOR_MASK 15 | ||
42 | #define TSDEV_BUFFER_SIZE 64 | ||
43 | |||
44 | #include <linux/slab.h> | ||
45 | #include <linux/poll.h> | ||
46 | #include <linux/module.h> | ||
47 | #include <linux/moduleparam.h> | ||
48 | #include <linux/init.h> | ||
49 | #include <linux/input.h> | ||
50 | #include <linux/major.h> | ||
51 | #include <linux/random.h> | ||
52 | #include <linux/time.h> | ||
53 | #include <linux/device.h> | ||
54 | |||
55 | #ifndef CONFIG_INPUT_TSDEV_SCREEN_X | ||
56 | #define CONFIG_INPUT_TSDEV_SCREEN_X 240 | ||
57 | #endif | ||
58 | #ifndef CONFIG_INPUT_TSDEV_SCREEN_Y | ||
59 | #define CONFIG_INPUT_TSDEV_SCREEN_Y 320 | ||
60 | #endif | ||
61 | |||
62 | /* This driver emulates both protocols of the old h3600_ts and h3600_tsraw | ||
63 | * devices. The first one must output X/Y data in 'cooked' format, e.g. | ||
64 | * filtered, dejittered and calibrated. Second device just outputs raw | ||
65 | * data received from the hardware. | ||
66 | * | ||
67 | * This driver doesn't support filtering and dejittering; it supports only | ||
68 | * calibration. Filtering and dejittering must be done in the low-level | ||
69 | * driver, if needed, because it may gain additional benefits from knowing | ||
70 | * the low-level details, the nature of noise and so on. | ||
71 | * | ||
72 | * The driver precomputes a calibration matrix given the initial xres and | ||
73 | * yres values (quite innacurate for most touchscreens) that will result | ||
74 | * in a more or less expected range of output values. The driver supports | ||
75 | * the TS_SET_CAL ioctl, which will replace the calibration matrix with a | ||
76 | * new one, supposedly generated from the values taken from the raw device. | ||
77 | */ | ||
78 | |||
79 | MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>"); | ||
80 | MODULE_DESCRIPTION("Input driver to touchscreen converter"); | ||
81 | MODULE_LICENSE("GPL"); | ||
82 | |||
83 | static int xres = CONFIG_INPUT_TSDEV_SCREEN_X; | ||
84 | module_param(xres, uint, 0); | ||
85 | MODULE_PARM_DESC(xres, "Horizontal screen resolution (can be negative for X-mirror)"); | ||
86 | |||
87 | static int yres = CONFIG_INPUT_TSDEV_SCREEN_Y; | ||
88 | module_param(yres, uint, 0); | ||
89 | MODULE_PARM_DESC(yres, "Vertical screen resolution (can be negative for Y-mirror)"); | ||
90 | |||
91 | /* From Compaq's Touch Screen Specification version 0.2 (draft) */ | ||
92 | struct ts_event { | ||
93 | short pressure; | ||
94 | short x; | ||
95 | short y; | ||
96 | short millisecs; | ||
97 | }; | ||
98 | |||
99 | struct ts_calibration { | ||
100 | int xscale; | ||
101 | int xtrans; | ||
102 | int yscale; | ||
103 | int ytrans; | ||
104 | int xyswap; | ||
105 | }; | ||
106 | |||
107 | struct tsdev { | ||
108 | int exist; | ||
109 | int open; | ||
110 | int minor; | ||
111 | char name[8]; | ||
112 | struct input_handle handle; | ||
113 | wait_queue_head_t wait; | ||
114 | struct list_head client_list; | ||
115 | struct device dev; | ||
116 | |||
117 | int x, y, pressure; | ||
118 | struct ts_calibration cal; | ||
119 | }; | ||
120 | |||
121 | struct tsdev_client { | ||
122 | struct fasync_struct *fasync; | ||
123 | struct list_head node; | ||
124 | struct tsdev *tsdev; | ||
125 | int head, tail; | ||
126 | struct ts_event event[TSDEV_BUFFER_SIZE]; | ||
127 | int raw; | ||
128 | }; | ||
129 | |||
130 | /* The following ioctl codes are defined ONLY for backward compatibility. | ||
131 | * Don't use tsdev for new developement; use the tslib library instead. | ||
132 | * Touchscreen calibration is a fully userspace task. | ||
133 | */ | ||
134 | /* Use 'f' as magic number */ | ||
135 | #define IOC_H3600_TS_MAGIC 'f' | ||
136 | #define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration) | ||
137 | #define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration) | ||
138 | |||
139 | static struct tsdev *tsdev_table[TSDEV_MINORS/2]; | ||
140 | |||
141 | static int tsdev_fasync(int fd, struct file *file, int on) | ||
142 | { | ||
143 | struct tsdev_client *client = file->private_data; | ||
144 | int retval; | ||
145 | |||
146 | retval = fasync_helper(fd, file, on, &client->fasync); | ||
147 | return retval < 0 ? retval : 0; | ||
148 | } | ||
149 | |||
150 | static int tsdev_open(struct inode *inode, struct file *file) | ||
151 | { | ||
152 | int i = iminor(inode) - TSDEV_MINOR_BASE; | ||
153 | struct tsdev_client *client; | ||
154 | struct tsdev *tsdev; | ||
155 | int error; | ||
156 | |||
157 | printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled " | ||
158 | "for removal.\nSee Documentation/feature-removal-schedule.txt " | ||
159 | "for details.\n"); | ||
160 | |||
161 | if (i >= TSDEV_MINORS) | ||
162 | return -ENODEV; | ||
163 | |||
164 | tsdev = tsdev_table[i & TSDEV_MINOR_MASK]; | ||
165 | if (!tsdev || !tsdev->exist) | ||
166 | return -ENODEV; | ||
167 | |||
168 | get_device(&tsdev->dev); | ||
169 | |||
170 | client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL); | ||
171 | if (!client) { | ||
172 | error = -ENOMEM; | ||
173 | goto err_put_tsdev; | ||
174 | } | ||
175 | |||
176 | client->tsdev = tsdev; | ||
177 | client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0; | ||
178 | list_add_tail(&client->node, &tsdev->client_list); | ||
179 | |||
180 | if (!tsdev->open++ && tsdev->exist) { | ||
181 | error = input_open_device(&tsdev->handle); | ||
182 | if (error) | ||
183 | goto err_free_client; | ||
184 | } | ||
185 | |||
186 | file->private_data = client; | ||
187 | return 0; | ||
188 | |||
189 | err_free_client: | ||
190 | list_del(&client->node); | ||
191 | kfree(client); | ||
192 | err_put_tsdev: | ||
193 | put_device(&tsdev->dev); | ||
194 | return error; | ||
195 | } | ||
196 | |||
197 | static void tsdev_free(struct device *dev) | ||
198 | { | ||
199 | struct tsdev *tsdev = container_of(dev, struct tsdev, dev); | ||
200 | |||
201 | tsdev_table[tsdev->minor] = NULL; | ||
202 | kfree(tsdev); | ||
203 | } | ||
204 | |||
205 | static int tsdev_release(struct inode *inode, struct file *file) | ||
206 | { | ||
207 | struct tsdev_client *client = file->private_data; | ||
208 | struct tsdev *tsdev = client->tsdev; | ||
209 | |||
210 | tsdev_fasync(-1, file, 0); | ||
211 | |||
212 | list_del(&client->node); | ||
213 | kfree(client); | ||
214 | |||
215 | if (!--tsdev->open && tsdev->exist) | ||
216 | input_close_device(&tsdev->handle); | ||
217 | |||
218 | put_device(&tsdev->dev); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count, | ||
224 | loff_t *ppos) | ||
225 | { | ||
226 | struct tsdev_client *client = file->private_data; | ||
227 | struct tsdev *tsdev = client->tsdev; | ||
228 | int retval = 0; | ||
229 | |||
230 | if (client->head == client->tail && tsdev->exist && (file->f_flags & O_NONBLOCK)) | ||
231 | return -EAGAIN; | ||
232 | |||
233 | retval = wait_event_interruptible(tsdev->wait, | ||
234 | client->head != client->tail || !tsdev->exist); | ||
235 | if (retval) | ||
236 | return retval; | ||
237 | |||
238 | if (!tsdev->exist) | ||
239 | return -ENODEV; | ||
240 | |||
241 | while (client->head != client->tail && | ||
242 | retval + sizeof (struct ts_event) <= count) { | ||
243 | if (copy_to_user (buffer + retval, client->event + client->tail, | ||
244 | sizeof (struct ts_event))) | ||
245 | return -EFAULT; | ||
246 | client->tail = (client->tail + 1) & (TSDEV_BUFFER_SIZE - 1); | ||
247 | retval += sizeof (struct ts_event); | ||
248 | } | ||
249 | |||
250 | return retval; | ||
251 | } | ||
252 | |||
253 | /* No kernel lock - fine */ | ||
254 | static unsigned int tsdev_poll(struct file *file, poll_table *wait) | ||
255 | { | ||
256 | struct tsdev_client *client = file->private_data; | ||
257 | struct tsdev *tsdev = client->tsdev; | ||
258 | |||
259 | poll_wait(file, &tsdev->wait, wait); | ||
260 | return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) | | ||
261 | (tsdev->exist ? 0 : (POLLHUP | POLLERR)); | ||
262 | } | ||
263 | |||
264 | static int tsdev_ioctl(struct inode *inode, struct file *file, | ||
265 | unsigned int cmd, unsigned long arg) | ||
266 | { | ||
267 | struct tsdev_client *client = file->private_data; | ||
268 | struct tsdev *tsdev = client->tsdev; | ||
269 | int retval = 0; | ||
270 | |||
271 | switch (cmd) { | ||
272 | case TS_GET_CAL: | ||
273 | if (copy_to_user((void __user *)arg, &tsdev->cal, | ||
274 | sizeof (struct ts_calibration))) | ||
275 | retval = -EFAULT; | ||
276 | break; | ||
277 | |||
278 | case TS_SET_CAL: | ||
279 | if (copy_from_user(&tsdev->cal, (void __user *)arg, | ||
280 | sizeof (struct ts_calibration))) | ||
281 | retval = -EFAULT; | ||
282 | break; | ||
283 | |||
284 | default: | ||
285 | retval = -EINVAL; | ||
286 | break; | ||
287 | } | ||
288 | |||
289 | return retval; | ||
290 | } | ||
291 | |||
292 | static const struct file_operations tsdev_fops = { | ||
293 | .owner = THIS_MODULE, | ||
294 | .open = tsdev_open, | ||
295 | .release = tsdev_release, | ||
296 | .read = tsdev_read, | ||
297 | .poll = tsdev_poll, | ||
298 | .fasync = tsdev_fasync, | ||
299 | .ioctl = tsdev_ioctl, | ||
300 | }; | ||
301 | |||
302 | static void tsdev_event(struct input_handle *handle, unsigned int type, | ||
303 | unsigned int code, int value) | ||
304 | { | ||
305 | struct tsdev *tsdev = handle->private; | ||
306 | struct tsdev_client *client; | ||
307 | struct timeval time; | ||
308 | |||
309 | switch (type) { | ||
310 | case EV_ABS: | ||
311 | switch (code) { | ||
312 | case ABS_X: | ||
313 | tsdev->x = value; | ||
314 | break; | ||
315 | |||
316 | case ABS_Y: | ||
317 | tsdev->y = value; | ||
318 | break; | ||
319 | |||
320 | case ABS_PRESSURE: | ||
321 | if (value > handle->dev->absmax[ABS_PRESSURE]) | ||
322 | value = handle->dev->absmax[ABS_PRESSURE]; | ||
323 | value -= handle->dev->absmin[ABS_PRESSURE]; | ||
324 | if (value < 0) | ||
325 | value = 0; | ||
326 | tsdev->pressure = value; | ||
327 | break; | ||
328 | } | ||
329 | break; | ||
330 | |||
331 | case EV_REL: | ||
332 | switch (code) { | ||
333 | case REL_X: | ||
334 | tsdev->x += value; | ||
335 | if (tsdev->x < 0) | ||
336 | tsdev->x = 0; | ||
337 | else if (tsdev->x > xres) | ||
338 | tsdev->x = xres; | ||
339 | break; | ||
340 | |||
341 | case REL_Y: | ||
342 | tsdev->y += value; | ||
343 | if (tsdev->y < 0) | ||
344 | tsdev->y = 0; | ||
345 | else if (tsdev->y > yres) | ||
346 | tsdev->y = yres; | ||
347 | break; | ||
348 | } | ||
349 | break; | ||
350 | |||
351 | case EV_KEY: | ||
352 | if (code == BTN_TOUCH || code == BTN_MOUSE) { | ||
353 | switch (value) { | ||
354 | case 0: | ||
355 | tsdev->pressure = 0; | ||
356 | break; | ||
357 | |||
358 | case 1: | ||
359 | if (!tsdev->pressure) | ||
360 | tsdev->pressure = 1; | ||
361 | break; | ||
362 | } | ||
363 | } | ||
364 | break; | ||
365 | } | ||
366 | |||
367 | if (type != EV_SYN || code != SYN_REPORT) | ||
368 | return; | ||
369 | |||
370 | list_for_each_entry(client, &tsdev->client_list, node) { | ||
371 | int x, y, tmp; | ||
372 | |||
373 | do_gettimeofday(&time); | ||
374 | client->event[client->head].millisecs = time.tv_usec / 1000; | ||
375 | client->event[client->head].pressure = tsdev->pressure; | ||
376 | |||
377 | x = tsdev->x; | ||
378 | y = tsdev->y; | ||
379 | |||
380 | /* Calibration */ | ||
381 | if (!client->raw) { | ||
382 | x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans; | ||
383 | y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans; | ||
384 | if (tsdev->cal.xyswap) { | ||
385 | tmp = x; x = y; y = tmp; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | client->event[client->head].x = x; | ||
390 | client->event[client->head].y = y; | ||
391 | client->head = (client->head + 1) & (TSDEV_BUFFER_SIZE - 1); | ||
392 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
393 | } | ||
394 | wake_up_interruptible(&tsdev->wait); | ||
395 | } | ||
396 | |||
397 | static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, | ||
398 | const struct input_device_id *id) | ||
399 | { | ||
400 | struct tsdev *tsdev; | ||
401 | int minor, delta; | ||
402 | int error; | ||
403 | |||
404 | for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++); | ||
405 | if (minor >= TSDEV_MINORS / 2) { | ||
406 | printk(KERN_ERR | ||
407 | "tsdev: You have way too many touchscreens\n"); | ||
408 | return -ENFILE; | ||
409 | } | ||
410 | |||
411 | tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL); | ||
412 | if (!tsdev) | ||
413 | return -ENOMEM; | ||
414 | |||
415 | INIT_LIST_HEAD(&tsdev->client_list); | ||
416 | init_waitqueue_head(&tsdev->wait); | ||
417 | |||
418 | tsdev->exist = 1; | ||
419 | tsdev->minor = minor; | ||
420 | tsdev->handle.dev = dev; | ||
421 | tsdev->handle.name = tsdev->name; | ||
422 | tsdev->handle.handler = handler; | ||
423 | tsdev->handle.private = tsdev; | ||
424 | snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor); | ||
425 | |||
426 | /* Precompute the rough calibration matrix */ | ||
427 | delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1; | ||
428 | if (delta == 0) | ||
429 | delta = 1; | ||
430 | tsdev->cal.xscale = (xres << 8) / delta; | ||
431 | tsdev->cal.xtrans = - ((dev->absmin [ABS_X] * tsdev->cal.xscale) >> 8); | ||
432 | |||
433 | delta = dev->absmax [ABS_Y] - dev->absmin [ABS_Y] + 1; | ||
434 | if (delta == 0) | ||
435 | delta = 1; | ||
436 | tsdev->cal.yscale = (yres << 8) / delta; | ||
437 | tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8); | ||
438 | |||
439 | snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id), | ||
440 | "ts%d", minor); | ||
441 | tsdev->dev.class = &input_class; | ||
442 | tsdev->dev.parent = &dev->dev; | ||
443 | tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor); | ||
444 | tsdev->dev.release = tsdev_free; | ||
445 | device_initialize(&tsdev->dev); | ||
446 | |||
447 | tsdev_table[minor] = tsdev; | ||
448 | |||
449 | error = device_add(&tsdev->dev); | ||
450 | if (error) | ||
451 | goto err_free_tsdev; | ||
452 | |||
453 | error = input_register_handle(&tsdev->handle); | ||
454 | if (error) | ||
455 | goto err_delete_tsdev; | ||
456 | |||
457 | return 0; | ||
458 | |||
459 | err_delete_tsdev: | ||
460 | device_del(&tsdev->dev); | ||
461 | err_free_tsdev: | ||
462 | put_device(&tsdev->dev); | ||
463 | return error; | ||
464 | } | ||
465 | |||
466 | static void tsdev_disconnect(struct input_handle *handle) | ||
467 | { | ||
468 | struct tsdev *tsdev = handle->private; | ||
469 | struct tsdev_client *client; | ||
470 | |||
471 | input_unregister_handle(handle); | ||
472 | device_del(&tsdev->dev); | ||
473 | |||
474 | tsdev->exist = 0; | ||
475 | |||
476 | if (tsdev->open) { | ||
477 | input_close_device(handle); | ||
478 | list_for_each_entry(client, &tsdev->client_list, node) | ||
479 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
480 | wake_up_interruptible(&tsdev->wait); | ||
481 | } | ||
482 | |||
483 | put_device(&tsdev->dev); | ||
484 | } | ||
485 | |||
486 | static const struct input_device_id tsdev_ids[] = { | ||
487 | { | ||
488 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, | ||
489 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, | ||
490 | .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, | ||
491 | .relbit = { BIT(REL_X) | BIT(REL_Y) }, | ||
492 | }, /* A mouse like device, at least one button, two relative axes */ | ||
493 | |||
494 | { | ||
495 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
496 | .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, | ||
497 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, | ||
498 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, | ||
499 | }, /* A tablet like device, at least touch detection, two absolute axes */ | ||
500 | |||
501 | { | ||
502 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
503 | .evbit = { BIT(EV_ABS) }, | ||
504 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) }, | ||
505 | }, /* A tablet like device with several gradations of pressure */ | ||
506 | |||
507 | {} /* Terminating entry */ | ||
508 | }; | ||
509 | |||
510 | MODULE_DEVICE_TABLE(input, tsdev_ids); | ||
511 | |||
512 | static struct input_handler tsdev_handler = { | ||
513 | .event = tsdev_event, | ||
514 | .connect = tsdev_connect, | ||
515 | .disconnect = tsdev_disconnect, | ||
516 | .fops = &tsdev_fops, | ||
517 | .minor = TSDEV_MINOR_BASE, | ||
518 | .name = "tsdev", | ||
519 | .id_table = tsdev_ids, | ||
520 | }; | ||
521 | |||
522 | static int __init tsdev_init(void) | ||
523 | { | ||
524 | return input_register_handler(&tsdev_handler); | ||
525 | } | ||
526 | |||
527 | static void __exit tsdev_exit(void) | ||
528 | { | ||
529 | input_unregister_handler(&tsdev_handler); | ||
530 | } | ||
531 | |||
532 | module_init(tsdev_init); | ||
533 | module_exit(tsdev_exit); | ||