diff options
Diffstat (limited to 'drivers/input')
48 files changed, 1394 insertions, 1107 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 556264b43425..374f404e81da 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/smp_lock.h> | 21 | #include <linux/smp_lock.h> |
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/devfs_fs_kernel.h> | 23 | #include <linux/devfs_fs_kernel.h> |
24 | #include <linux/compat.h> | ||
24 | 25 | ||
25 | struct evdev { | 26 | struct evdev { |
26 | int exist; | 27 | int exist; |
@@ -145,6 +146,41 @@ static int evdev_open(struct inode * inode, struct file * file) | |||
145 | return 0; | 146 | return 0; |
146 | } | 147 | } |
147 | 148 | ||
149 | #ifdef CONFIG_COMPAT | ||
150 | struct input_event_compat { | ||
151 | struct compat_timeval time; | ||
152 | __u16 type; | ||
153 | __u16 code; | ||
154 | __s32 value; | ||
155 | }; | ||
156 | |||
157 | #ifdef CONFIG_X86_64 | ||
158 | # define COMPAT_TEST test_thread_flag(TIF_IA32) | ||
159 | #elif defined(CONFIG_IA64) | ||
160 | # define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current)) | ||
161 | #elif defined(CONFIG_ARCH_S390) | ||
162 | # define COMPAT_TEST test_thread_flag(TIF_31BIT) | ||
163 | #else | ||
164 | # define COMPAT_TEST test_thread_flag(TIF_32BIT) | ||
165 | #endif | ||
166 | |||
167 | static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) | ||
168 | { | ||
169 | struct evdev_list *list = file->private_data; | ||
170 | struct input_event_compat event; | ||
171 | int retval = 0; | ||
172 | |||
173 | while (retval < count) { | ||
174 | if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat))) | ||
175 | return -EFAULT; | ||
176 | input_event(list->evdev->handle.dev, event.type, event.code, event.value); | ||
177 | retval += sizeof(struct input_event_compat); | ||
178 | } | ||
179 | |||
180 | return retval; | ||
181 | } | ||
182 | #endif | ||
183 | |||
148 | static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) | 184 | static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) |
149 | { | 185 | { |
150 | struct evdev_list *list = file->private_data; | 186 | struct evdev_list *list = file->private_data; |
@@ -153,6 +189,11 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ | |||
153 | 189 | ||
154 | if (!list->evdev->exist) return -ENODEV; | 190 | if (!list->evdev->exist) return -ENODEV; |
155 | 191 | ||
192 | #ifdef CONFIG_COMPAT | ||
193 | if (COMPAT_TEST) | ||
194 | return evdev_write_compat(file, buffer, count, ppos); | ||
195 | #endif | ||
196 | |||
156 | while (retval < count) { | 197 | while (retval < count) { |
157 | 198 | ||
158 | if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) | 199 | if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) |
@@ -164,11 +205,56 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ | |||
164 | return retval; | 205 | return retval; |
165 | } | 206 | } |
166 | 207 | ||
208 | #ifdef CONFIG_COMPAT | ||
209 | static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos) | ||
210 | { | ||
211 | struct evdev_list *list = file->private_data; | ||
212 | int retval; | ||
213 | |||
214 | if (count < sizeof(struct input_event_compat)) | ||
215 | return -EINVAL; | ||
216 | |||
217 | if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) | ||
218 | return -EAGAIN; | ||
219 | |||
220 | retval = wait_event_interruptible(list->evdev->wait, | ||
221 | list->head != list->tail || (!list->evdev->exist)); | ||
222 | |||
223 | if (retval) | ||
224 | return retval; | ||
225 | |||
226 | if (!list->evdev->exist) | ||
227 | return -ENODEV; | ||
228 | |||
229 | while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) { | ||
230 | struct input_event *event = (struct input_event *) list->buffer + list->tail; | ||
231 | struct input_event_compat event_compat; | ||
232 | event_compat.time.tv_sec = event->time.tv_sec; | ||
233 | event_compat.time.tv_usec = event->time.tv_usec; | ||
234 | event_compat.type = event->type; | ||
235 | event_compat.code = event->code; | ||
236 | event_compat.value = event->value; | ||
237 | |||
238 | if (copy_to_user(buffer + retval, &event_compat, | ||
239 | sizeof(struct input_event_compat))) return -EFAULT; | ||
240 | list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
241 | retval += sizeof(struct input_event_compat); | ||
242 | } | ||
243 | |||
244 | return retval; | ||
245 | } | ||
246 | #endif | ||
247 | |||
167 | static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) | 248 | static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) |
168 | { | 249 | { |
169 | struct evdev_list *list = file->private_data; | 250 | struct evdev_list *list = file->private_data; |
170 | int retval; | 251 | int retval; |
171 | 252 | ||
253 | #ifdef CONFIG_COMPAT | ||
254 | if (COMPAT_TEST) | ||
255 | return evdev_read_compat(file, buffer, count, ppos); | ||
256 | #endif | ||
257 | |||
172 | if (count < sizeof(struct input_event)) | 258 | if (count < sizeof(struct input_event)) |
173 | return -EINVAL; | 259 | return -EINVAL; |
174 | 260 | ||
@@ -186,7 +272,7 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count | |||
186 | 272 | ||
187 | while (list->head != list->tail && retval + sizeof(struct input_event) <= count) { | 273 | while (list->head != list->tail && retval + sizeof(struct input_event) <= count) { |
188 | if (copy_to_user(buffer + retval, list->buffer + list->tail, | 274 | if (copy_to_user(buffer + retval, list->buffer + list->tail, |
189 | sizeof(struct input_event))) return -EFAULT; | 275 | sizeof(struct input_event))) return -EFAULT; |
190 | list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); | 276 | list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); |
191 | retval += sizeof(struct input_event); | 277 | retval += sizeof(struct input_event); |
192 | } | 278 | } |
@@ -203,7 +289,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait) | |||
203 | (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); | 289 | (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); |
204 | } | 290 | } |
205 | 291 | ||
206 | static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 292 | static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
207 | { | 293 | { |
208 | struct evdev_list *list = file->private_data; | 294 | struct evdev_list *list = file->private_data; |
209 | struct evdev *evdev = list->evdev; | 295 | struct evdev *evdev = list->evdev; |
@@ -285,109 +371,267 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
285 | 371 | ||
286 | default: | 372 | default: |
287 | 373 | ||
288 | if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) | 374 | if (_IOC_TYPE(cmd) != 'E') |
289 | return -EINVAL; | 375 | return -EINVAL; |
290 | 376 | ||
291 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | 377 | if (_IOC_DIR(cmd) == _IOC_READ) { |
292 | 378 | ||
293 | long *bits; | 379 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { |
294 | int len; | 380 | |
295 | 381 | long *bits; | |
296 | switch (_IOC_NR(cmd) & EV_MAX) { | 382 | int len; |
297 | case 0: bits = dev->evbit; len = EV_MAX; break; | 383 | |
298 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | 384 | switch (_IOC_NR(cmd) & EV_MAX) { |
299 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; | 385 | case 0: bits = dev->evbit; len = EV_MAX; break; |
300 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | 386 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; |
301 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | 387 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; |
302 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | 388 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; |
303 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | 389 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; |
304 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | 390 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; |
305 | default: return -EINVAL; | 391 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; |
392 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
393 | default: return -EINVAL; | ||
394 | } | ||
395 | len = NBITS(len) * sizeof(long); | ||
396 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
397 | return copy_to_user(p, bits, len) ? -EFAULT : len; | ||
306 | } | 398 | } |
307 | len = NBITS(len) * sizeof(long); | ||
308 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
309 | return copy_to_user(p, bits, len) ? -EFAULT : len; | ||
310 | } | ||
311 | 399 | ||
312 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { | 400 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { |
313 | int len; | 401 | int len; |
314 | len = NBITS(KEY_MAX) * sizeof(long); | 402 | len = NBITS(KEY_MAX) * sizeof(long); |
315 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 403 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
316 | return copy_to_user(p, dev->key, len) ? -EFAULT : len; | 404 | return copy_to_user(p, dev->key, len) ? -EFAULT : len; |
317 | } | 405 | } |
318 | 406 | ||
319 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { | 407 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { |
320 | int len; | 408 | int len; |
321 | len = NBITS(LED_MAX) * sizeof(long); | 409 | len = NBITS(LED_MAX) * sizeof(long); |
322 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 410 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
323 | return copy_to_user(p, dev->led, len) ? -EFAULT : len; | 411 | return copy_to_user(p, dev->led, len) ? -EFAULT : len; |
324 | } | 412 | } |
325 | 413 | ||
326 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { | 414 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { |
327 | int len; | 415 | int len; |
328 | len = NBITS(SND_MAX) * sizeof(long); | 416 | len = NBITS(SND_MAX) * sizeof(long); |
329 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 417 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
330 | return copy_to_user(p, dev->snd, len) ? -EFAULT : len; | 418 | return copy_to_user(p, dev->snd, len) ? -EFAULT : len; |
331 | } | 419 | } |
332 | 420 | ||
333 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { | 421 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { |
334 | int len; | 422 | int len; |
335 | if (!dev->name) return -ENOENT; | 423 | if (!dev->name) return -ENOENT; |
336 | len = strlen(dev->name) + 1; | 424 | len = strlen(dev->name) + 1; |
337 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 425 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
338 | return copy_to_user(p, dev->name, len) ? -EFAULT : len; | 426 | return copy_to_user(p, dev->name, len) ? -EFAULT : len; |
339 | } | 427 | } |
428 | |||
429 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | ||
430 | int len; | ||
431 | if (!dev->phys) return -ENOENT; | ||
432 | len = strlen(dev->phys) + 1; | ||
433 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
434 | return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | ||
435 | } | ||
436 | |||
437 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | ||
438 | int len; | ||
439 | if (!dev->uniq) return -ENOENT; | ||
440 | len = strlen(dev->uniq) + 1; | ||
441 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
442 | return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | ||
443 | } | ||
444 | |||
445 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | ||
446 | |||
447 | int t = _IOC_NR(cmd) & ABS_MAX; | ||
448 | |||
449 | abs.value = dev->abs[t]; | ||
450 | abs.minimum = dev->absmin[t]; | ||
451 | abs.maximum = dev->absmax[t]; | ||
452 | abs.fuzz = dev->absfuzz[t]; | ||
453 | abs.flat = dev->absflat[t]; | ||
454 | |||
455 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | ||
456 | return -EFAULT; | ||
457 | |||
458 | return 0; | ||
459 | } | ||
340 | 460 | ||
341 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | ||
342 | int len; | ||
343 | if (!dev->phys) return -ENOENT; | ||
344 | len = strlen(dev->phys) + 1; | ||
345 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
346 | return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | ||
347 | } | 461 | } |
348 | 462 | ||
349 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | 463 | if (_IOC_DIR(cmd) == _IOC_WRITE) { |
350 | int len; | 464 | |
351 | if (!dev->uniq) return -ENOENT; | 465 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
352 | len = strlen(dev->uniq) + 1; | 466 | |
353 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 467 | int t = _IOC_NR(cmd) & ABS_MAX; |
354 | return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | 468 | |
469 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | ||
470 | return -EFAULT; | ||
471 | |||
472 | dev->abs[t] = abs.value; | ||
473 | dev->absmin[t] = abs.minimum; | ||
474 | dev->absmax[t] = abs.maximum; | ||
475 | dev->absfuzz[t] = abs.fuzz; | ||
476 | dev->absflat[t] = abs.flat; | ||
477 | |||
478 | return 0; | ||
479 | } | ||
355 | } | 480 | } |
481 | } | ||
482 | return -EINVAL; | ||
483 | } | ||
356 | 484 | ||
357 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | 485 | #ifdef CONFIG_COMPAT |
486 | |||
487 | #define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) | ||
488 | #define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1) | ||
489 | #define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT) | ||
490 | #define BIT_COMPAT(x) (1UL<<OFF_COMPAT(x)) | ||
491 | #define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT) | ||
492 | #define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1) | ||
493 | |||
494 | #ifdef __BIG_ENDIAN | ||
495 | #define bit_to_user(bit, max) \ | ||
496 | do { \ | ||
497 | int i; \ | ||
498 | int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ | ||
499 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ | ||
500 | for (i = 0; i < len / sizeof(compat_long_t); i++) \ | ||
501 | if (copy_to_user((compat_long_t*) p + i, \ | ||
502 | (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \ | ||
503 | sizeof(compat_long_t))) \ | ||
504 | return -EFAULT; \ | ||
505 | return len; \ | ||
506 | } while (0) | ||
507 | #else | ||
508 | #define bit_to_user(bit, max) \ | ||
509 | do { \ | ||
510 | int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ | ||
511 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ | ||
512 | return copy_to_user(p, (bit), len) ? -EFAULT : len; \ | ||
513 | } while (0) | ||
514 | #endif | ||
515 | |||
516 | static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | ||
517 | { | ||
518 | struct evdev_list *list = file->private_data; | ||
519 | struct evdev *evdev = list->evdev; | ||
520 | struct input_dev *dev = evdev->handle.dev; | ||
521 | struct input_absinfo abs; | ||
522 | void __user *p = compat_ptr(arg); | ||
358 | 523 | ||
359 | int t = _IOC_NR(cmd) & ABS_MAX; | 524 | if (!evdev->exist) return -ENODEV; |
360 | 525 | ||
361 | abs.value = dev->abs[t]; | 526 | switch (cmd) { |
362 | abs.minimum = dev->absmin[t]; | ||
363 | abs.maximum = dev->absmax[t]; | ||
364 | abs.fuzz = dev->absfuzz[t]; | ||
365 | abs.flat = dev->absflat[t]; | ||
366 | 527 | ||
367 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | 528 | case EVIOCGVERSION: |
368 | return -EFAULT; | 529 | case EVIOCGID: |
530 | case EVIOCGKEYCODE: | ||
531 | case EVIOCSKEYCODE: | ||
532 | case EVIOCSFF: | ||
533 | case EVIOCRMFF: | ||
534 | case EVIOCGEFFECTS: | ||
535 | case EVIOCGRAB: | ||
536 | return evdev_ioctl(file, cmd, (unsigned long) p); | ||
369 | 537 | ||
370 | return 0; | 538 | default: |
539 | |||
540 | if (_IOC_TYPE(cmd) != 'E') | ||
541 | return -EINVAL; | ||
542 | |||
543 | if (_IOC_DIR(cmd) == _IOC_READ) { | ||
544 | |||
545 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | ||
546 | long *bits; | ||
547 | int max; | ||
548 | |||
549 | switch (_IOC_NR(cmd) & EV_MAX) { | ||
550 | case 0: bits = dev->evbit; max = EV_MAX; break; | ||
551 | case EV_KEY: bits = dev->keybit; max = KEY_MAX; break; | ||
552 | case EV_REL: bits = dev->relbit; max = REL_MAX; break; | ||
553 | case EV_ABS: bits = dev->absbit; max = ABS_MAX; break; | ||
554 | case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break; | ||
555 | case EV_LED: bits = dev->ledbit; max = LED_MAX; break; | ||
556 | case EV_SND: bits = dev->sndbit; max = SND_MAX; break; | ||
557 | case EV_FF: bits = dev->ffbit; max = FF_MAX; break; | ||
558 | default: return -EINVAL; | ||
559 | } | ||
560 | bit_to_user(bits, max); | ||
561 | } | ||
562 | |||
563 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | ||
564 | bit_to_user(dev->key, KEY_MAX); | ||
565 | |||
566 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) | ||
567 | bit_to_user(dev->led, LED_MAX); | ||
568 | |||
569 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) | ||
570 | bit_to_user(dev->snd, SND_MAX); | ||
571 | |||
572 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { | ||
573 | int len; | ||
574 | if (!dev->name) return -ENOENT; | ||
575 | len = strlen(dev->name) + 1; | ||
576 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
577 | return copy_to_user(p, dev->name, len) ? -EFAULT : len; | ||
578 | } | ||
579 | |||
580 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | ||
581 | int len; | ||
582 | if (!dev->phys) return -ENOENT; | ||
583 | len = strlen(dev->phys) + 1; | ||
584 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
585 | return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | ||
586 | } | ||
587 | |||
588 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | ||
589 | int len; | ||
590 | if (!dev->uniq) return -ENOENT; | ||
591 | len = strlen(dev->uniq) + 1; | ||
592 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
593 | return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | ||
594 | } | ||
595 | |||
596 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | ||
597 | |||
598 | int t = _IOC_NR(cmd) & ABS_MAX; | ||
599 | |||
600 | abs.value = dev->abs[t]; | ||
601 | abs.minimum = dev->absmin[t]; | ||
602 | abs.maximum = dev->absmax[t]; | ||
603 | abs.fuzz = dev->absfuzz[t]; | ||
604 | abs.flat = dev->absflat[t]; | ||
605 | |||
606 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | ||
607 | return -EFAULT; | ||
608 | |||
609 | return 0; | ||
610 | } | ||
371 | } | 611 | } |
372 | 612 | ||
373 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | 613 | if (_IOC_DIR(cmd) == _IOC_WRITE) { |
374 | 614 | ||
375 | int t = _IOC_NR(cmd) & ABS_MAX; | 615 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
376 | 616 | ||
377 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | 617 | int t = _IOC_NR(cmd) & ABS_MAX; |
378 | return -EFAULT; | ||
379 | 618 | ||
380 | dev->abs[t] = abs.value; | 619 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) |
381 | dev->absmin[t] = abs.minimum; | 620 | return -EFAULT; |
382 | dev->absmax[t] = abs.maximum; | ||
383 | dev->absfuzz[t] = abs.fuzz; | ||
384 | dev->absflat[t] = abs.flat; | ||
385 | 621 | ||
386 | return 0; | 622 | dev->abs[t] = abs.value; |
623 | dev->absmin[t] = abs.minimum; | ||
624 | dev->absmax[t] = abs.maximum; | ||
625 | dev->absfuzz[t] = abs.fuzz; | ||
626 | dev->absflat[t] = abs.flat; | ||
627 | |||
628 | return 0; | ||
629 | } | ||
387 | } | 630 | } |
388 | } | 631 | } |
389 | return -EINVAL; | 632 | return -EINVAL; |
390 | } | 633 | } |
634 | #endif | ||
391 | 635 | ||
392 | static struct file_operations evdev_fops = { | 636 | static struct file_operations evdev_fops = { |
393 | .owner = THIS_MODULE, | 637 | .owner = THIS_MODULE, |
@@ -396,7 +640,10 @@ static struct file_operations evdev_fops = { | |||
396 | .poll = evdev_poll, | 640 | .poll = evdev_poll, |
397 | .open = evdev_open, | 641 | .open = evdev_open, |
398 | .release = evdev_release, | 642 | .release = evdev_release, |
399 | .ioctl = evdev_ioctl, | 643 | .unlocked_ioctl = evdev_ioctl, |
644 | #ifdef CONFIG_COMPAT | ||
645 | .compat_ioctl = evdev_ioctl_compat, | ||
646 | #endif | ||
400 | .fasync = evdev_fasync, | 647 | .fasync = evdev_fasync, |
401 | .flush = evdev_flush | 648 | .flush = evdev_flush |
402 | }; | 649 | }; |
diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig index 1d93f5092904..7524bd7d8b8f 100644 --- a/drivers/input/gameport/Kconfig +++ b/drivers/input/gameport/Kconfig | |||
@@ -49,22 +49,8 @@ config GAMEPORT_EMU10K1 | |||
49 | To compile this driver as a module, choose M here: the | 49 | To compile this driver as a module, choose M here: the |
50 | module will be called emu10k1-gp. | 50 | module will be called emu10k1-gp. |
51 | 51 | ||
52 | config GAMEPORT_VORTEX | ||
53 | tristate "Aureal Vortex, Vortex 2 gameport support" | ||
54 | depends on PCI | ||
55 | help | ||
56 | Say Y here if you have an Aureal Vortex 1 or 2 card and want | ||
57 | to use its gameport. | ||
58 | |||
59 | To compile this driver as a module, choose M here: the | ||
60 | module will be called vortex. | ||
61 | |||
62 | config GAMEPORT_FM801 | 52 | config GAMEPORT_FM801 |
63 | tristate "ForteMedia FM801 gameport support" | 53 | tristate "ForteMedia FM801 gameport support" |
64 | depends on PCI | 54 | depends on PCI |
65 | 55 | ||
66 | config GAMEPORT_CS461X | ||
67 | tristate "Crystal SoundFusion gameport support" | ||
68 | depends on PCI | ||
69 | |||
70 | endif | 56 | endif |
diff --git a/drivers/input/gameport/Makefile b/drivers/input/gameport/Makefile index 5367b4267adf..b6f6097bd8c4 100644 --- a/drivers/input/gameport/Makefile +++ b/drivers/input/gameport/Makefile | |||
@@ -5,9 +5,7 @@ | |||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_GAMEPORT) += gameport.o | 7 | obj-$(CONFIG_GAMEPORT) += gameport.o |
8 | obj-$(CONFIG_GAMEPORT_CS461X) += cs461x.o | ||
9 | obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o | 8 | obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o |
10 | obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o | 9 | obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o |
11 | obj-$(CONFIG_GAMEPORT_L4) += lightning.o | 10 | obj-$(CONFIG_GAMEPORT_L4) += lightning.o |
12 | obj-$(CONFIG_GAMEPORT_NS558) += ns558.o | 11 | obj-$(CONFIG_GAMEPORT_NS558) += ns558.o |
13 | obj-$(CONFIG_GAMEPORT_VORTEX) += vortex.o | ||
diff --git a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c deleted file mode 100644 index d4013ff98623..000000000000 --- a/drivers/input/gameport/cs461x.c +++ /dev/null | |||
@@ -1,322 +0,0 @@ | |||
1 | /* | ||
2 | The all defines and part of code (such as cs461x_*) are | ||
3 | contributed from ALSA 0.5.8 sources. | ||
4 | See http://www.alsa-project.org/ for sources | ||
5 | |||
6 | Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610 | ||
7 | */ | ||
8 | |||
9 | #include <asm/io.h> | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/ioport.h> | ||
13 | #include <linux/config.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/gameport.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/pci.h> | ||
18 | |||
19 | MODULE_AUTHOR("Victor Krapivin"); | ||
20 | MODULE_LICENSE("GPL"); | ||
21 | |||
22 | /* | ||
23 | These options are experimental | ||
24 | |||
25 | #define CS461X_FULL_MAP | ||
26 | */ | ||
27 | |||
28 | |||
29 | #ifndef PCI_VENDOR_ID_CIRRUS | ||
30 | #define PCI_VENDOR_ID_CIRRUS 0x1013 | ||
31 | #endif | ||
32 | #ifndef PCI_DEVICE_ID_CIRRUS_4610 | ||
33 | #define PCI_DEVICE_ID_CIRRUS_4610 0x6001 | ||
34 | #endif | ||
35 | #ifndef PCI_DEVICE_ID_CIRRUS_4612 | ||
36 | #define PCI_DEVICE_ID_CIRRUS_4612 0x6003 | ||
37 | #endif | ||
38 | #ifndef PCI_DEVICE_ID_CIRRUS_4615 | ||
39 | #define PCI_DEVICE_ID_CIRRUS_4615 0x6004 | ||
40 | #endif | ||
41 | |||
42 | /* Registers */ | ||
43 | |||
44 | #define BA0_JSPT 0x00000480 | ||
45 | #define BA0_JSCTL 0x00000484 | ||
46 | #define BA0_JSC1 0x00000488 | ||
47 | #define BA0_JSC2 0x0000048C | ||
48 | #define BA0_JSIO 0x000004A0 | ||
49 | |||
50 | /* Bits for JSPT */ | ||
51 | |||
52 | #define JSPT_CAX 0x00000001 | ||
53 | #define JSPT_CAY 0x00000002 | ||
54 | #define JSPT_CBX 0x00000004 | ||
55 | #define JSPT_CBY 0x00000008 | ||
56 | #define JSPT_BA1 0x00000010 | ||
57 | #define JSPT_BA2 0x00000020 | ||
58 | #define JSPT_BB1 0x00000040 | ||
59 | #define JSPT_BB2 0x00000080 | ||
60 | |||
61 | /* Bits for JSCTL */ | ||
62 | |||
63 | #define JSCTL_SP_MASK 0x00000003 | ||
64 | #define JSCTL_SP_SLOW 0x00000000 | ||
65 | #define JSCTL_SP_MEDIUM_SLOW 0x00000001 | ||
66 | #define JSCTL_SP_MEDIUM_FAST 0x00000002 | ||
67 | #define JSCTL_SP_FAST 0x00000003 | ||
68 | #define JSCTL_ARE 0x00000004 | ||
69 | |||
70 | /* Data register pairs masks */ | ||
71 | |||
72 | #define JSC1_Y1V_MASK 0x0000FFFF | ||
73 | #define JSC1_X1V_MASK 0xFFFF0000 | ||
74 | #define JSC1_Y1V_SHIFT 0 | ||
75 | #define JSC1_X1V_SHIFT 16 | ||
76 | #define JSC2_Y2V_MASK 0x0000FFFF | ||
77 | #define JSC2_X2V_MASK 0xFFFF0000 | ||
78 | #define JSC2_Y2V_SHIFT 0 | ||
79 | #define JSC2_X2V_SHIFT 16 | ||
80 | |||
81 | /* JS GPIO */ | ||
82 | |||
83 | #define JSIO_DAX 0x00000001 | ||
84 | #define JSIO_DAY 0x00000002 | ||
85 | #define JSIO_DBX 0x00000004 | ||
86 | #define JSIO_DBY 0x00000008 | ||
87 | #define JSIO_AXOE 0x00000010 | ||
88 | #define JSIO_AYOE 0x00000020 | ||
89 | #define JSIO_BXOE 0x00000040 | ||
90 | #define JSIO_BYOE 0x00000080 | ||
91 | |||
92 | /* | ||
93 | The card initialization code is obfuscated; the module cs461x | ||
94 | need to be loaded after ALSA modules initialized and something | ||
95 | played on the CS 4610 chip (see sources for details of CS4610 | ||
96 | initialization code from ALSA) | ||
97 | */ | ||
98 | |||
99 | /* Card specific definitions */ | ||
100 | |||
101 | #define CS461X_BA0_SIZE 0x2000 | ||
102 | #define CS461X_BA1_DATA0_SIZE 0x3000 | ||
103 | #define CS461X_BA1_DATA1_SIZE 0x3800 | ||
104 | #define CS461X_BA1_PRG_SIZE 0x7000 | ||
105 | #define CS461X_BA1_REG_SIZE 0x0100 | ||
106 | |||
107 | #define BA1_SP_DMEM0 0x00000000 | ||
108 | #define BA1_SP_DMEM1 0x00010000 | ||
109 | #define BA1_SP_PMEM 0x00020000 | ||
110 | #define BA1_SP_REG 0x00030000 | ||
111 | |||
112 | #define BA1_DWORD_SIZE (13 * 1024 + 512) | ||
113 | #define BA1_MEMORY_COUNT 3 | ||
114 | |||
115 | /* | ||
116 | Only one CS461x card is still suppoted; the code requires | ||
117 | redesign to avoid this limitatuion. | ||
118 | */ | ||
119 | |||
120 | static unsigned long ba0_addr; | ||
121 | static unsigned int __iomem *ba0; | ||
122 | |||
123 | #ifdef CS461X_FULL_MAP | ||
124 | static unsigned long ba1_addr; | ||
125 | static union ba1_t { | ||
126 | struct { | ||
127 | unsigned int __iomem *data0; | ||
128 | unsigned int __iomem *data1; | ||
129 | unsigned int __iomem *pmem; | ||
130 | unsigned int __iomem *reg; | ||
131 | } name; | ||
132 | unsigned int __iomem *idx[4]; | ||
133 | } ba1; | ||
134 | |||
135 | static void cs461x_poke(unsigned long reg, unsigned int val) | ||
136 | { | ||
137 | writel(val, &ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); | ||
138 | } | ||
139 | |||
140 | static unsigned int cs461x_peek(unsigned long reg) | ||
141 | { | ||
142 | return readl(&ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); | ||
143 | } | ||
144 | |||
145 | #endif | ||
146 | |||
147 | static void cs461x_pokeBA0(unsigned long reg, unsigned int val) | ||
148 | { | ||
149 | writel(val, &ba0[reg >> 2]); | ||
150 | } | ||
151 | |||
152 | static unsigned int cs461x_peekBA0(unsigned long reg) | ||
153 | { | ||
154 | return readl(&ba0[reg >> 2]); | ||
155 | } | ||
156 | |||
157 | static int cs461x_free(struct pci_dev *pdev) | ||
158 | { | ||
159 | struct gameport *port = pci_get_drvdata(pdev); | ||
160 | |||
161 | if (port) | ||
162 | gameport_unregister_port(port); | ||
163 | |||
164 | if (ba0) iounmap(ba0); | ||
165 | #ifdef CS461X_FULL_MAP | ||
166 | if (ba1.name.data0) iounmap(ba1.name.data0); | ||
167 | if (ba1.name.data1) iounmap(ba1.name.data1); | ||
168 | if (ba1.name.pmem) iounmap(ba1.name.pmem); | ||
169 | if (ba1.name.reg) iounmap(ba1.name.reg); | ||
170 | #endif | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static void cs461x_gameport_trigger(struct gameport *gameport) | ||
175 | { | ||
176 | cs461x_pokeBA0(BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); | ||
177 | } | ||
178 | |||
179 | static unsigned char cs461x_gameport_read(struct gameport *gameport) | ||
180 | { | ||
181 | return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io); | ||
182 | } | ||
183 | |||
184 | static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) | ||
185 | { | ||
186 | unsigned js1, js2, jst; | ||
187 | |||
188 | js1 = cs461x_peekBA0(BA0_JSC1); | ||
189 | js2 = cs461x_peekBA0(BA0_JSC2); | ||
190 | jst = cs461x_peekBA0(BA0_JSPT); | ||
191 | |||
192 | *buttons = (~jst >> 4) & 0x0F; | ||
193 | |||
194 | axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; | ||
195 | axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; | ||
196 | axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; | ||
197 | axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; | ||
198 | |||
199 | for(jst=0;jst<4;++jst) | ||
200 | if(axes[jst]==0xFFFF) axes[jst] = -1; | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int cs461x_gameport_open(struct gameport *gameport, int mode) | ||
205 | { | ||
206 | switch (mode) { | ||
207 | case GAMEPORT_MODE_COOKED: | ||
208 | case GAMEPORT_MODE_RAW: | ||
209 | return 0; | ||
210 | default: | ||
211 | return -1; | ||
212 | } | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static struct pci_device_id cs461x_pci_tbl[] = { | ||
217 | { PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */ | ||
218 | { PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */ | ||
219 | { PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */ | ||
220 | { 0, } | ||
221 | }; | ||
222 | MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl); | ||
223 | |||
224 | static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
225 | { | ||
226 | int rc; | ||
227 | struct gameport* port; | ||
228 | |||
229 | rc = pci_enable_device(pdev); | ||
230 | if (rc) { | ||
231 | printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n", | ||
232 | pdev->bus->number, pdev->devfn, rc); | ||
233 | return rc; | ||
234 | } | ||
235 | |||
236 | ba0_addr = pci_resource_start(pdev, 0); | ||
237 | #ifdef CS461X_FULL_MAP | ||
238 | ba1_addr = pci_resource_start(pdev, 1); | ||
239 | #endif | ||
240 | if (ba0_addr == 0 || ba0_addr == ~0 | ||
241 | #ifdef CS461X_FULL_MAP | ||
242 | || ba1_addr == 0 || ba1_addr == ~0 | ||
243 | #endif | ||
244 | ) { | ||
245 | printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr); | ||
246 | #ifdef CS461X_FULL_MAP | ||
247 | printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr); | ||
248 | #endif | ||
249 | cs461x_free(pdev); | ||
250 | return -ENOMEM; | ||
251 | } | ||
252 | |||
253 | ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE); | ||
254 | #ifdef CS461X_FULL_MAP | ||
255 | ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE); | ||
256 | ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE); | ||
257 | ba1.name.pmem = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE); | ||
258 | ba1.name.reg = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE); | ||
259 | |||
260 | if (ba0 == NULL || ba1.name.data0 == NULL || | ||
261 | ba1.name.data1 == NULL || ba1.name.pmem == NULL || | ||
262 | ba1.name.reg == NULL) { | ||
263 | cs461x_free(pdev); | ||
264 | return -ENOMEM; | ||
265 | } | ||
266 | #else | ||
267 | if (ba0 == NULL) { | ||
268 | cs461x_free(pdev); | ||
269 | return -ENOMEM; | ||
270 | } | ||
271 | #endif | ||
272 | |||
273 | if (!(port = gameport_allocate_port())) { | ||
274 | printk(KERN_ERR "cs461x: Memory allocation failed\n"); | ||
275 | cs461x_free(pdev); | ||
276 | return -ENOMEM; | ||
277 | } | ||
278 | |||
279 | pci_set_drvdata(pdev, port); | ||
280 | |||
281 | port->open = cs461x_gameport_open; | ||
282 | port->trigger = cs461x_gameport_trigger; | ||
283 | port->read = cs461x_gameport_read; | ||
284 | port->cooked_read = cs461x_gameport_cooked_read; | ||
285 | |||
286 | gameport_set_name(port, "CS416x"); | ||
287 | gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev)); | ||
288 | port->dev.parent = &pdev->dev; | ||
289 | |||
290 | cs461x_pokeBA0(BA0_JSIO, 0xFF); // ? | ||
291 | cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); | ||
292 | |||
293 | gameport_register_port(port); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static void __devexit cs461x_pci_remove(struct pci_dev *pdev) | ||
299 | { | ||
300 | cs461x_free(pdev); | ||
301 | } | ||
302 | |||
303 | static struct pci_driver cs461x_pci_driver = { | ||
304 | .name = "CS461x_gameport", | ||
305 | .id_table = cs461x_pci_tbl, | ||
306 | .probe = cs461x_pci_probe, | ||
307 | .remove = __devexit_p(cs461x_pci_remove), | ||
308 | }; | ||
309 | |||
310 | static int __init cs461x_init(void) | ||
311 | { | ||
312 | return pci_register_driver(&cs461x_pci_driver); | ||
313 | } | ||
314 | |||
315 | static void __exit cs461x_exit(void) | ||
316 | { | ||
317 | pci_unregister_driver(&cs461x_pci_driver); | ||
318 | } | ||
319 | |||
320 | module_init(cs461x_init); | ||
321 | module_exit(cs461x_exit); | ||
322 | |||
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index c77a82e46055..ab09cf4093e3 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -17,11 +17,10 @@ | |||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/gameport.h> | 18 | #include <linux/gameport.h> |
19 | #include <linux/wait.h> | 19 | #include <linux/wait.h> |
20 | #include <linux/completion.h> | ||
21 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
22 | #include <linux/smp_lock.h> | ||
23 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
24 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/kthread.h> | ||
25 | 24 | ||
26 | /*#include <asm/io.h>*/ | 25 | /*#include <asm/io.h>*/ |
27 | 26 | ||
@@ -61,12 +60,13 @@ static void gameport_disconnect_port(struct gameport *gameport); | |||
61 | 60 | ||
62 | #if defined(__i386__) | 61 | #if defined(__i386__) |
63 | 62 | ||
63 | #include <asm/i8253.h> | ||
64 | |||
64 | #define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0)) | 65 | #define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0)) |
65 | #define GET_TIME(x) do { x = get_time_pit(); } while (0) | 66 | #define GET_TIME(x) do { x = get_time_pit(); } while (0) |
66 | 67 | ||
67 | static unsigned int get_time_pit(void) | 68 | static unsigned int get_time_pit(void) |
68 | { | 69 | { |
69 | extern spinlock_t i8253_lock; | ||
70 | unsigned long flags; | 70 | unsigned long flags; |
71 | unsigned int count; | 71 | unsigned int count; |
72 | 72 | ||
@@ -238,8 +238,7 @@ struct gameport_event { | |||
238 | static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ | 238 | static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ |
239 | static LIST_HEAD(gameport_event_list); | 239 | static LIST_HEAD(gameport_event_list); |
240 | static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); | 240 | static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); |
241 | static DECLARE_COMPLETION(gameport_exited); | 241 | static struct task_struct *gameport_task; |
242 | static int gameport_pid; | ||
243 | 242 | ||
244 | static void gameport_queue_event(void *object, struct module *owner, | 243 | static void gameport_queue_event(void *object, struct module *owner, |
245 | enum gameport_event_type event_type) | 244 | enum gameport_event_type event_type) |
@@ -250,12 +249,12 @@ static void gameport_queue_event(void *object, struct module *owner, | |||
250 | spin_lock_irqsave(&gameport_event_lock, flags); | 249 | spin_lock_irqsave(&gameport_event_lock, flags); |
251 | 250 | ||
252 | /* | 251 | /* |
253 | * Scan event list for the other events for the same gameport port, | 252 | * Scan event list for the other events for the same gameport port, |
254 | * starting with the most recent one. If event is the same we | 253 | * starting with the most recent one. If event is the same we |
255 | * do not need add new one. If event is of different type we | 254 | * do not need add new one. If event is of different type we |
256 | * need to add this event and should not look further because | 255 | * need to add this event and should not look further because |
257 | * we need to preseve sequence of distinct events. | 256 | * we need to preseve sequence of distinct events. |
258 | */ | 257 | */ |
259 | list_for_each_entry_reverse(event, &gameport_event_list, node) { | 258 | list_for_each_entry_reverse(event, &gameport_event_list, node) { |
260 | if (event->object == object) { | 259 | if (event->object == object) { |
261 | if (event->type == event_type) | 260 | if (event->type == event_type) |
@@ -432,20 +431,15 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent) | |||
432 | 431 | ||
433 | static int gameport_thread(void *nothing) | 432 | static int gameport_thread(void *nothing) |
434 | { | 433 | { |
435 | lock_kernel(); | ||
436 | daemonize("kgameportd"); | ||
437 | allow_signal(SIGTERM); | ||
438 | |||
439 | do { | 434 | do { |
440 | gameport_handle_events(); | 435 | gameport_handle_events(); |
441 | wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list)); | 436 | wait_event_interruptible(gameport_wait, |
437 | kthread_should_stop() || !list_empty(&gameport_event_list)); | ||
442 | try_to_freeze(); | 438 | try_to_freeze(); |
443 | } while (!signal_pending(current)); | 439 | } while (!kthread_should_stop()); |
444 | 440 | ||
445 | printk(KERN_DEBUG "gameport: kgameportd exiting\n"); | 441 | printk(KERN_DEBUG "gameport: kgameportd exiting\n"); |
446 | 442 | return 0; | |
447 | unlock_kernel(); | ||
448 | complete_and_exit(&gameport_exited, 0); | ||
449 | } | 443 | } |
450 | 444 | ||
451 | 445 | ||
@@ -773,9 +767,10 @@ void gameport_close(struct gameport *gameport) | |||
773 | 767 | ||
774 | static int __init gameport_init(void) | 768 | static int __init gameport_init(void) |
775 | { | 769 | { |
776 | if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) { | 770 | gameport_task = kthread_run(gameport_thread, NULL, "kgameportd"); |
771 | if (IS_ERR(gameport_task)) { | ||
777 | printk(KERN_ERR "gameport: Failed to start kgameportd\n"); | 772 | printk(KERN_ERR "gameport: Failed to start kgameportd\n"); |
778 | return -1; | 773 | return PTR_ERR(gameport_task); |
779 | } | 774 | } |
780 | 775 | ||
781 | gameport_bus.dev_attrs = gameport_device_attrs; | 776 | gameport_bus.dev_attrs = gameport_device_attrs; |
@@ -789,8 +784,7 @@ static int __init gameport_init(void) | |||
789 | static void __exit gameport_exit(void) | 784 | static void __exit gameport_exit(void) |
790 | { | 785 | { |
791 | bus_unregister(&gameport_bus); | 786 | bus_unregister(&gameport_bus); |
792 | kill_proc(gameport_pid, SIGTERM, 1); | 787 | kthread_stop(gameport_task); |
793 | wait_for_completion(&gameport_exited); | ||
794 | } | 788 | } |
795 | 789 | ||
796 | module_init(gameport_init); | 790 | module_init(gameport_init); |
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index 7c5c6318eeb9..1ab5f2dc8a2a 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c | |||
@@ -258,18 +258,18 @@ static int __init ns558_init(void) | |||
258 | { | 258 | { |
259 | int i = 0; | 259 | int i = 0; |
260 | 260 | ||
261 | if (pnp_register_driver(&ns558_pnp_driver) >= 0) | ||
262 | pnp_registered = 1; | ||
263 | |||
261 | /* | 264 | /* |
262 | * Probe ISA ports first so that PnP gets to choose free port addresses | 265 | * Probe ISA ports after PnP, so that PnP ports that are already |
263 | * not occupied by the ISA ports. | 266 | * enabled get detected as PnP. This may be suboptimal in multi-device |
267 | * configurations, but saves hassle with simple setups. | ||
264 | */ | 268 | */ |
265 | 269 | ||
266 | while (ns558_isa_portlist[i]) | 270 | while (ns558_isa_portlist[i]) |
267 | ns558_isa_probe(ns558_isa_portlist[i++]); | 271 | ns558_isa_probe(ns558_isa_portlist[i++]); |
268 | 272 | ||
269 | if (pnp_register_driver(&ns558_pnp_driver) >= 0) | ||
270 | pnp_registered = 1; | ||
271 | |||
272 | |||
273 | return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; | 273 | return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; |
274 | } | 274 | } |
275 | 275 | ||
diff --git a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c deleted file mode 100644 index 36b0309c8bf6..000000000000 --- a/drivers/input/gameport/vortex.c +++ /dev/null | |||
@@ -1,186 +0,0 @@ | |||
1 | /* | ||
2 | * $Id: vortex.c,v 1.5 2002/07/01 15:39:30 vojtech Exp $ | ||
3 | * | ||
4 | * Copyright (c) 2000-2001 Vojtech Pavlik | ||
5 | * | ||
6 | * Based on the work of: | ||
7 | * Raymond Ingles | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Trident 4DWave and Aureal Vortex gameport driver for Linux | ||
12 | */ | ||
13 | |||
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, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | * | ||
29 | * Should you need to contact me, the author, you can do so either by | ||
30 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
31 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
32 | */ | ||
33 | |||
34 | #include <asm/io.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/ioport.h> | ||
38 | #include <linux/kernel.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/pci.h> | ||
41 | #include <linux/init.h> | ||
42 | #include <linux/slab.h> | ||
43 | #include <linux/delay.h> | ||
44 | #include <linux/gameport.h> | ||
45 | |||
46 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | ||
47 | MODULE_DESCRIPTION("Aureal Vortex and Vortex2 gameport driver"); | ||
48 | MODULE_LICENSE("GPL"); | ||
49 | |||
50 | #define VORTEX_GCR 0x0c /* Gameport control register */ | ||
51 | #define VORTEX_LEG 0x08 /* Legacy port location */ | ||
52 | #define VORTEX_AXD 0x10 /* Axes start */ | ||
53 | #define VORTEX_DATA_WAIT 20 /* 20 ms */ | ||
54 | |||
55 | struct vortex { | ||
56 | struct gameport *gameport; | ||
57 | struct pci_dev *dev; | ||
58 | unsigned char __iomem *base; | ||
59 | unsigned char __iomem *io; | ||
60 | }; | ||
61 | |||
62 | static unsigned char vortex_read(struct gameport *gameport) | ||
63 | { | ||
64 | struct vortex *vortex = gameport->port_data; | ||
65 | return readb(vortex->io + VORTEX_LEG); | ||
66 | } | ||
67 | |||
68 | static void vortex_trigger(struct gameport *gameport) | ||
69 | { | ||
70 | struct vortex *vortex = gameport->port_data; | ||
71 | writeb(0xff, vortex->io + VORTEX_LEG); | ||
72 | } | ||
73 | |||
74 | static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons) | ||
75 | { | ||
76 | struct vortex *vortex = gameport->port_data; | ||
77 | int i; | ||
78 | |||
79 | *buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf; | ||
80 | |||
81 | for (i = 0; i < 4; i++) { | ||
82 | axes[i] = readw(vortex->io + VORTEX_AXD + i * sizeof(u32)); | ||
83 | if (axes[i] == 0x1fff) axes[i] = -1; | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int vortex_open(struct gameport *gameport, int mode) | ||
90 | { | ||
91 | struct vortex *vortex = gameport->port_data; | ||
92 | |||
93 | switch (mode) { | ||
94 | case GAMEPORT_MODE_COOKED: | ||
95 | writeb(0x40, vortex->io + VORTEX_GCR); | ||
96 | msleep(VORTEX_DATA_WAIT); | ||
97 | return 0; | ||
98 | case GAMEPORT_MODE_RAW: | ||
99 | writeb(0x00, vortex->io + VORTEX_GCR); | ||
100 | return 0; | ||
101 | default: | ||
102 | return -1; | ||
103 | } | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
109 | { | ||
110 | struct vortex *vortex; | ||
111 | struct gameport *port; | ||
112 | int i; | ||
113 | |||
114 | vortex = kcalloc(1, sizeof(struct vortex), GFP_KERNEL); | ||
115 | port = gameport_allocate_port(); | ||
116 | if (!vortex || !port) { | ||
117 | printk(KERN_ERR "vortex: Memory allocation failed.\n"); | ||
118 | kfree(vortex); | ||
119 | gameport_free_port(port); | ||
120 | return -ENOMEM; | ||
121 | } | ||
122 | |||
123 | for (i = 0; i < 6; i++) | ||
124 | if (~pci_resource_flags(dev, i) & IORESOURCE_IO) | ||
125 | break; | ||
126 | |||
127 | pci_enable_device(dev); | ||
128 | |||
129 | vortex->dev = dev; | ||
130 | vortex->gameport = port; | ||
131 | vortex->base = ioremap(pci_resource_start(vortex->dev, i), | ||
132 | pci_resource_len(vortex->dev, i)); | ||
133 | vortex->io = vortex->base + id->driver_data; | ||
134 | |||
135 | pci_set_drvdata(dev, vortex); | ||
136 | |||
137 | port->port_data = vortex; | ||
138 | port->fuzz = 64; | ||
139 | |||
140 | gameport_set_name(port, "AU88x0"); | ||
141 | gameport_set_phys(port, "pci%s/gameport0", pci_name(dev)); | ||
142 | port->dev.parent = &dev->dev; | ||
143 | port->read = vortex_read; | ||
144 | port->trigger = vortex_trigger; | ||
145 | port->cooked_read = vortex_cooked_read; | ||
146 | port->open = vortex_open; | ||
147 | |||
148 | gameport_register_port(port); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static void __devexit vortex_remove(struct pci_dev *dev) | ||
154 | { | ||
155 | struct vortex *vortex = pci_get_drvdata(dev); | ||
156 | |||
157 | gameport_unregister_port(vortex->gameport); | ||
158 | iounmap(vortex->base); | ||
159 | kfree(vortex); | ||
160 | } | ||
161 | |||
162 | static struct pci_device_id vortex_id_table[] = { | ||
163 | { 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 }, | ||
164 | { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 }, | ||
165 | { 0 } | ||
166 | }; | ||
167 | |||
168 | static struct pci_driver vortex_driver = { | ||
169 | .name = "vortex_gameport", | ||
170 | .id_table = vortex_id_table, | ||
171 | .probe = vortex_probe, | ||
172 | .remove = __devexit_p(vortex_remove), | ||
173 | }; | ||
174 | |||
175 | static int __init vortex_init(void) | ||
176 | { | ||
177 | return pci_register_driver(&vortex_driver); | ||
178 | } | ||
179 | |||
180 | static void __exit vortex_exit(void) | ||
181 | { | ||
182 | pci_unregister_driver(&vortex_driver); | ||
183 | } | ||
184 | |||
185 | module_init(vortex_init); | ||
186 | module_exit(vortex_exit); | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index 83c77c990dda..7c4b4d37b3e6 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -219,10 +219,24 @@ void input_release_device(struct input_handle *handle) | |||
219 | 219 | ||
220 | int input_open_device(struct input_handle *handle) | 220 | int input_open_device(struct input_handle *handle) |
221 | { | 221 | { |
222 | struct input_dev *dev = handle->dev; | ||
223 | int err; | ||
224 | |||
225 | err = down_interruptible(&dev->sem); | ||
226 | if (err) | ||
227 | return err; | ||
228 | |||
222 | handle->open++; | 229 | handle->open++; |
223 | if (handle->dev->open) | 230 | |
224 | return handle->dev->open(handle->dev); | 231 | if (!dev->users++ && dev->open) |
225 | return 0; | 232 | err = dev->open(dev); |
233 | |||
234 | if (err) | ||
235 | handle->open--; | ||
236 | |||
237 | up(&dev->sem); | ||
238 | |||
239 | return err; | ||
226 | } | 240 | } |
227 | 241 | ||
228 | int input_flush_device(struct input_handle* handle, struct file* file) | 242 | int input_flush_device(struct input_handle* handle, struct file* file) |
@@ -235,10 +249,17 @@ int input_flush_device(struct input_handle* handle, struct file* file) | |||
235 | 249 | ||
236 | void input_close_device(struct input_handle *handle) | 250 | void input_close_device(struct input_handle *handle) |
237 | { | 251 | { |
252 | struct input_dev *dev = handle->dev; | ||
253 | |||
238 | input_release_device(handle); | 254 | input_release_device(handle); |
239 | if (handle->dev->close) | 255 | |
240 | handle->dev->close(handle->dev); | 256 | down(&dev->sem); |
257 | |||
258 | if (!--dev->users && dev->close) | ||
259 | dev->close(dev); | ||
241 | handle->open--; | 260 | handle->open--; |
261 | |||
262 | up(&dev->sem); | ||
242 | } | 263 | } |
243 | 264 | ||
244 | static void input_link_handle(struct input_handle *handle) | 265 | static void input_link_handle(struct input_handle *handle) |
@@ -415,6 +436,8 @@ void input_register_device(struct input_dev *dev) | |||
415 | 436 | ||
416 | set_bit(EV_SYN, dev->evbit); | 437 | set_bit(EV_SYN, dev->evbit); |
417 | 438 | ||
439 | init_MUTEX(&dev->sem); | ||
440 | |||
418 | /* | 441 | /* |
419 | * If delay and period are pre-set by the driver, then autorepeating | 442 | * If delay and period are pre-set by the driver, then autorepeating |
420 | * is handled by the driver itself and we don't do it in input.c. | 443 | * is handled by the driver itself and we don't do it in input.c. |
@@ -674,6 +697,8 @@ static int input_handlers_read(char *buf, char **start, off_t pos, int count, in | |||
674 | return (count > cnt) ? cnt : count; | 697 | return (count > cnt) ? cnt : count; |
675 | } | 698 | } |
676 | 699 | ||
700 | static struct file_operations input_fileops; | ||
701 | |||
677 | static int __init input_proc_init(void) | 702 | static int __init input_proc_init(void) |
678 | { | 703 | { |
679 | struct proc_dir_entry *entry; | 704 | struct proc_dir_entry *entry; |
@@ -688,6 +713,8 @@ static int __init input_proc_init(void) | |||
688 | return -ENOMEM; | 713 | return -ENOMEM; |
689 | } | 714 | } |
690 | entry->owner = THIS_MODULE; | 715 | entry->owner = THIS_MODULE; |
716 | input_fileops = *entry->proc_fops; | ||
717 | entry->proc_fops = &input_fileops; | ||
691 | entry->proc_fops->poll = input_devices_poll; | 718 | entry->proc_fops->poll = input_devices_poll; |
692 | entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); | 719 | entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); |
693 | if (entry == NULL) { | 720 | if (entry == NULL) { |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 39775fc380c7..ff8e1bbd0e13 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -285,48 +285,33 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) | |||
285 | (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); | 285 | (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); |
286 | } | 286 | } |
287 | 287 | ||
288 | static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 288 | static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp) |
289 | { | 289 | { |
290 | struct joydev_list *list = file->private_data; | ||
291 | struct joydev *joydev = list->joydev; | ||
292 | struct input_dev *dev = joydev->handle.dev; | 290 | struct input_dev *dev = joydev->handle.dev; |
293 | void __user *argp = (void __user *)arg; | ||
294 | int i, j; | 291 | int i, j; |
295 | 292 | ||
296 | if (!joydev->exist) return -ENODEV; | ||
297 | |||
298 | switch (cmd) { | 293 | switch (cmd) { |
299 | 294 | ||
300 | case JS_SET_CAL: | 295 | case JS_SET_CAL: |
301 | return copy_from_user(&joydev->glue.JS_CORR, argp, | 296 | return copy_from_user(&joydev->glue.JS_CORR, argp, |
302 | sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; | 297 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
303 | case JS_GET_CAL: | 298 | case JS_GET_CAL: |
304 | return copy_to_user(argp, &joydev->glue.JS_CORR, | 299 | return copy_to_user(argp, &joydev->glue.JS_CORR, |
305 | sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; | 300 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
306 | case JS_SET_TIMEOUT: | 301 | case JS_SET_TIMEOUT: |
307 | return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); | 302 | return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
308 | case JS_GET_TIMEOUT: | 303 | case JS_GET_TIMEOUT: |
309 | return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); | 304 | return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
310 | case JS_SET_TIMELIMIT: | ||
311 | return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
312 | case JS_GET_TIMELIMIT: | ||
313 | return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
314 | case JS_SET_ALL: | ||
315 | return copy_from_user(&joydev->glue, argp, | ||
316 | sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; | ||
317 | case JS_GET_ALL: | ||
318 | return copy_to_user(argp, &joydev->glue, | ||
319 | sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; | ||
320 | 305 | ||
321 | case JSIOCGVERSION: | 306 | case JSIOCGVERSION: |
322 | return put_user(JS_VERSION, (__u32 __user *) arg); | 307 | return put_user(JS_VERSION, (__u32 __user *) argp); |
323 | case JSIOCGAXES: | 308 | case JSIOCGAXES: |
324 | return put_user(joydev->nabs, (__u8 __user *) arg); | 309 | return put_user(joydev->nabs, (__u8 __user *) argp); |
325 | case JSIOCGBUTTONS: | 310 | case JSIOCGBUTTONS: |
326 | return put_user(joydev->nkey, (__u8 __user *) arg); | 311 | return put_user(joydev->nkey, (__u8 __user *) argp); |
327 | case JSIOCSCORR: | 312 | case JSIOCSCORR: |
328 | if (copy_from_user(joydev->corr, argp, | 313 | if (copy_from_user(joydev->corr, argp, |
329 | sizeof(struct js_corr) * joydev->nabs)) | 314 | sizeof(joydev->corr[0]) * joydev->nabs)) |
330 | return -EFAULT; | 315 | return -EFAULT; |
331 | for (i = 0; i < joydev->nabs; i++) { | 316 | for (i = 0; i < joydev->nabs; i++) { |
332 | j = joydev->abspam[i]; | 317 | j = joydev->abspam[i]; |
@@ -335,7 +320,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
335 | return 0; | 320 | return 0; |
336 | case JSIOCGCORR: | 321 | case JSIOCGCORR: |
337 | return copy_to_user(argp, joydev->corr, | 322 | return copy_to_user(argp, joydev->corr, |
338 | sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0; | 323 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; |
339 | case JSIOCSAXMAP: | 324 | case JSIOCSAXMAP: |
340 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) | 325 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) |
341 | return -EFAULT; | 326 | return -EFAULT; |
@@ -371,6 +356,84 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
371 | return -EINVAL; | 356 | return -EINVAL; |
372 | } | 357 | } |
373 | 358 | ||
359 | #ifdef CONFIG_COMPAT | ||
360 | static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
361 | { | ||
362 | struct joydev_list *list = file->private_data; | ||
363 | struct joydev *joydev = list->joydev; | ||
364 | void __user *argp = (void __user *)arg; | ||
365 | s32 tmp32; | ||
366 | struct JS_DATA_SAVE_TYPE_32 ds32; | ||
367 | int err; | ||
368 | |||
369 | if (!joydev->exist) return -ENODEV; | ||
370 | switch(cmd) { | ||
371 | case JS_SET_TIMELIMIT: | ||
372 | err = get_user(tmp32, (s32 __user *) arg); | ||
373 | if (err == 0) | ||
374 | joydev->glue.JS_TIMELIMIT = tmp32; | ||
375 | break; | ||
376 | case JS_GET_TIMELIMIT: | ||
377 | tmp32 = joydev->glue.JS_TIMELIMIT; | ||
378 | err = put_user(tmp32, (s32 __user *) arg); | ||
379 | break; | ||
380 | |||
381 | case JS_SET_ALL: | ||
382 | err = copy_from_user(&ds32, argp, | ||
383 | sizeof(ds32)) ? -EFAULT : 0; | ||
384 | if (err == 0) { | ||
385 | joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT; | ||
386 | joydev->glue.BUSY = ds32.BUSY; | ||
387 | joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME; | ||
388 | joydev->glue.JS_TIMELIMIT = ds32.JS_TIMELIMIT; | ||
389 | joydev->glue.JS_SAVE = ds32.JS_SAVE; | ||
390 | joydev->glue.JS_CORR = ds32.JS_CORR; | ||
391 | } | ||
392 | break; | ||
393 | |||
394 | case JS_GET_ALL: | ||
395 | ds32.JS_TIMEOUT = joydev->glue.JS_TIMEOUT; | ||
396 | ds32.BUSY = joydev->glue.BUSY; | ||
397 | ds32.JS_EXPIRETIME = joydev->glue.JS_EXPIRETIME; | ||
398 | ds32.JS_TIMELIMIT = joydev->glue.JS_TIMELIMIT; | ||
399 | ds32.JS_SAVE = joydev->glue.JS_SAVE; | ||
400 | ds32.JS_CORR = joydev->glue.JS_CORR; | ||
401 | |||
402 | err = copy_to_user(argp, &ds32, | ||
403 | sizeof(ds32)) ? -EFAULT : 0; | ||
404 | break; | ||
405 | |||
406 | default: | ||
407 | err = joydev_ioctl_common(joydev, cmd, argp); | ||
408 | } | ||
409 | return err; | ||
410 | } | ||
411 | #endif /* CONFIG_COMPAT */ | ||
412 | |||
413 | static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
414 | { | ||
415 | struct joydev_list *list = file->private_data; | ||
416 | struct joydev *joydev = list->joydev; | ||
417 | void __user *argp = (void __user *)arg; | ||
418 | |||
419 | if (!joydev->exist) return -ENODEV; | ||
420 | |||
421 | switch(cmd) { | ||
422 | case JS_SET_TIMELIMIT: | ||
423 | return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
424 | case JS_GET_TIMELIMIT: | ||
425 | return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
426 | case JS_SET_ALL: | ||
427 | return copy_from_user(&joydev->glue, argp, | ||
428 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
429 | case JS_GET_ALL: | ||
430 | return copy_to_user(argp, &joydev->glue, | ||
431 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
432 | default: | ||
433 | return joydev_ioctl_common(joydev, cmd, argp); | ||
434 | } | ||
435 | } | ||
436 | |||
374 | static struct file_operations joydev_fops = { | 437 | static struct file_operations joydev_fops = { |
375 | .owner = THIS_MODULE, | 438 | .owner = THIS_MODULE, |
376 | .read = joydev_read, | 439 | .read = joydev_read, |
@@ -379,6 +442,9 @@ static struct file_operations joydev_fops = { | |||
379 | .open = joydev_open, | 442 | .open = joydev_open, |
380 | .release = joydev_release, | 443 | .release = joydev_release, |
381 | .ioctl = joydev_ioctl, | 444 | .ioctl = joydev_ioctl, |
445 | #ifdef CONFIG_COMPAT | ||
446 | .compat_ioctl = joydev_compat_ioctl, | ||
447 | #endif | ||
382 | .fasync = joydev_fasync, | 448 | .fasync = joydev_fasync, |
383 | }; | 449 | }; |
384 | 450 | ||
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index ad39fe4bf35f..bf34f75b9467 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c | |||
@@ -185,7 +185,7 @@ static void a3d_poll(struct gameport *gameport) | |||
185 | a3d->reads++; | 185 | a3d->reads++; |
186 | if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length || | 186 | if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length || |
187 | data[0] != a3d->mode || a3d_csum(data, a3d->length)) | 187 | data[0] != a3d->mode || a3d_csum(data, a3d->length)) |
188 | a3d->bads++; | 188 | a3d->bads++; |
189 | else | 189 | else |
190 | a3d_read(a3d, data); | 190 | a3d_read(a3d, data); |
191 | } | 191 | } |
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index 83f6dafc1716..265962956c63 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c | |||
@@ -82,7 +82,7 @@ static char adi_cm2_abs[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ }; | |||
82 | static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y }; | 82 | static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y }; |
83 | 83 | ||
84 | static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }; | 84 | static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }; |
85 | static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; | 85 | static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; |
86 | static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 }; | 86 | static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 }; |
87 | static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 }; | 87 | static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 }; |
88 | 88 | ||
@@ -183,7 +183,7 @@ static void adi_move_bits(struct adi_port *port, int length) | |||
183 | int i; | 183 | int i; |
184 | struct adi *adi = port->adi; | 184 | struct adi *adi = port->adi; |
185 | 185 | ||
186 | adi[0].idx = adi[1].idx = 0; | 186 | adi[0].idx = adi[1].idx = 0; |
187 | 187 | ||
188 | if (adi[0].ret <= 0 || adi[1].ret <= 0) return; | 188 | if (adi[0].ret <= 0 || adi[1].ret <= 0) return; |
189 | if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return; | 189 | if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return; |
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index cf36ca9b92f3..033456bb9fe0 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c | |||
@@ -51,7 +51,8 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is | |||
51 | 51 | ||
52 | __obsolete_setup("amijoy="); | 52 | __obsolete_setup("amijoy="); |
53 | 53 | ||
54 | static int amijoy_used[2] = { 0, 0 }; | 54 | static int amijoy_used; |
55 | static DECLARE_MUTEX(amijoy_sem); | ||
55 | static struct input_dev amijoy_dev[2]; | 56 | static struct input_dev amijoy_dev[2]; |
56 | static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; | 57 | static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; |
57 | 58 | ||
@@ -84,26 +85,30 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp) | |||
84 | 85 | ||
85 | static int amijoy_open(struct input_dev *dev) | 86 | static int amijoy_open(struct input_dev *dev) |
86 | { | 87 | { |
87 | int *used = dev->private; | 88 | int err; |
88 | 89 | ||
89 | if ((*used)++) | 90 | err = down_interruptible(&amijoy_sem); |
90 | return 0; | 91 | if (err) |
92 | return err; | ||
91 | 93 | ||
92 | if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) { | 94 | if (!amijoy_used && request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) { |
93 | (*used)--; | ||
94 | printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); | 95 | printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); |
95 | return -EBUSY; | 96 | err = -EBUSY; |
97 | goto out; | ||
96 | } | 98 | } |
97 | 99 | ||
98 | return 0; | 100 | amijoy_used++; |
101 | out: | ||
102 | up(&amijoy_sem); | ||
103 | return err; | ||
99 | } | 104 | } |
100 | 105 | ||
101 | static void amijoy_close(struct input_dev *dev) | 106 | static void amijoy_close(struct input_dev *dev) |
102 | { | 107 | { |
103 | int *used = dev->private; | 108 | down(&amijoysem); |
104 | 109 | if (!--amijoy_used) | |
105 | if (!--(*used)) | ||
106 | free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); | 110 | free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); |
111 | up(&amijoy_sem); | ||
107 | } | 112 | } |
108 | 113 | ||
109 | static int __init amijoy_init(void) | 114 | static int __init amijoy_init(void) |
@@ -138,8 +143,6 @@ static int __init amijoy_init(void) | |||
138 | amijoy_dev[i].id.product = 0x0003; | 143 | amijoy_dev[i].id.product = 0x0003; |
139 | amijoy_dev[i].id.version = 0x0100; | 144 | amijoy_dev[i].id.version = 0x0100; |
140 | 145 | ||
141 | amijoy_dev[i].private = amijoy_used + i; | ||
142 | |||
143 | input_register_device(amijoy_dev + i); | 146 | input_register_device(amijoy_dev + i); |
144 | printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i); | 147 | printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i); |
145 | } | 148 | } |
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 504b7d550567..c3a5739030c3 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -140,12 +140,14 @@ struct analog_port { | |||
140 | */ | 140 | */ |
141 | 141 | ||
142 | #ifdef __i386__ | 142 | #ifdef __i386__ |
143 | |||
144 | #include <asm/i8253.h> | ||
145 | |||
143 | #define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0) | 146 | #define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0) |
144 | #define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? CLOCK_TICK_RATE / HZ : 0))) | 147 | #define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? CLOCK_TICK_RATE / HZ : 0))) |
145 | #define TIME_NAME (cpu_has_tsc?"TSC":"PIT") | 148 | #define TIME_NAME (cpu_has_tsc?"TSC":"PIT") |
146 | static unsigned int get_time_pit(void) | 149 | static unsigned int get_time_pit(void) |
147 | { | 150 | { |
148 | extern spinlock_t i8253_lock; | ||
149 | unsigned long flags; | 151 | unsigned long flags; |
150 | unsigned int count; | 152 | unsigned int count; |
151 | 153 | ||
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index cfdd3acf06a1..fbd3eed07f90 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c | |||
@@ -87,7 +87,7 @@ __obsolete_setup("db9_3="); | |||
87 | #define DB9_NORMAL 0x0a | 87 | #define DB9_NORMAL 0x0a |
88 | #define DB9_NOSELECT 0x08 | 88 | #define DB9_NOSELECT 0x08 |
89 | 89 | ||
90 | #define DB9_MAX_DEVICES 2 | 90 | #define DB9_MAX_DEVICES 2 |
91 | 91 | ||
92 | #define DB9_GENESIS6_DELAY 14 | 92 | #define DB9_GENESIS6_DELAY 14 |
93 | #define DB9_REFRESH_TIME HZ/100 | 93 | #define DB9_REFRESH_TIME HZ/100 |
@@ -98,6 +98,7 @@ struct db9 { | |||
98 | struct pardevice *pd; | 98 | struct pardevice *pd; |
99 | int mode; | 99 | int mode; |
100 | int used; | 100 | int used; |
101 | struct semaphore sem; | ||
101 | char phys[2][32]; | 102 | char phys[2][32]; |
102 | }; | 103 | }; |
103 | 104 | ||
@@ -503,6 +504,11 @@ static int db9_open(struct input_dev *dev) | |||
503 | { | 504 | { |
504 | struct db9 *db9 = dev->private; | 505 | struct db9 *db9 = dev->private; |
505 | struct parport *port = db9->pd->port; | 506 | struct parport *port = db9->pd->port; |
507 | int err; | ||
508 | |||
509 | err = down_interruptible(&db9->sem); | ||
510 | if (err) | ||
511 | return err; | ||
506 | 512 | ||
507 | if (!db9->used++) { | 513 | if (!db9->used++) { |
508 | parport_claim(db9->pd); | 514 | parport_claim(db9->pd); |
@@ -514,6 +520,7 @@ static int db9_open(struct input_dev *dev) | |||
514 | mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); | 520 | mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); |
515 | } | 521 | } |
516 | 522 | ||
523 | up(&db9->sem); | ||
517 | return 0; | 524 | return 0; |
518 | } | 525 | } |
519 | 526 | ||
@@ -522,12 +529,14 @@ static void db9_close(struct input_dev *dev) | |||
522 | struct db9 *db9 = dev->private; | 529 | struct db9 *db9 = dev->private; |
523 | struct parport *port = db9->pd->port; | 530 | struct parport *port = db9->pd->port; |
524 | 531 | ||
532 | down(&db9->sem); | ||
525 | if (!--db9->used) { | 533 | if (!--db9->used) { |
526 | del_timer(&db9->timer); | 534 | del_timer_sync(&db9->timer); |
527 | parport_write_control(port, 0x00); | 535 | parport_write_control(port, 0x00); |
528 | parport_data_forward(port); | 536 | parport_data_forward(port); |
529 | parport_release(db9->pd); | 537 | parport_release(db9->pd); |
530 | } | 538 | } |
539 | up(&db9->sem); | ||
531 | } | 540 | } |
532 | 541 | ||
533 | static struct db9 __init *db9_probe(int *config, int nargs) | 542 | static struct db9 __init *db9_probe(int *config, int nargs) |
@@ -563,12 +572,12 @@ static struct db9 __init *db9_probe(int *config, int nargs) | |||
563 | } | 572 | } |
564 | } | 573 | } |
565 | 574 | ||
566 | if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL))) { | 575 | if (!(db9 = kcalloc(1, sizeof(struct db9), GFP_KERNEL))) { |
567 | parport_put_port(pp); | 576 | parport_put_port(pp); |
568 | return NULL; | 577 | return NULL; |
569 | } | 578 | } |
570 | memset(db9, 0, sizeof(struct db9)); | ||
571 | 579 | ||
580 | init_MUTEX(&db9->sem); | ||
572 | db9->mode = config[1]; | 581 | db9->mode = config[1]; |
573 | init_timer(&db9->timer); | 582 | init_timer(&db9->timer); |
574 | db9->timer.data = (long) db9; | 583 | db9->timer.data = (long) db9; |
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 8732f52bdd08..95bbdd302aad 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c | |||
@@ -1,12 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux | 2 | * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux |
3 | * | 3 | * |
4 | * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz> | 4 | * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz> |
5 | * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org> | 5 | * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org> |
6 | * | 6 | * |
7 | * Based on the work of: | 7 | * Based on the work of: |
8 | * Andree Borrmann John Dahlstrom | 8 | * Andree Borrmann John Dahlstrom |
9 | * David Kuder Nathan Hand | 9 | * David Kuder Nathan Hand |
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* | 12 | /* |
@@ -81,6 +81,7 @@ struct gc { | |||
81 | struct timer_list timer; | 81 | struct timer_list timer; |
82 | unsigned char pads[GC_MAX + 1]; | 82 | unsigned char pads[GC_MAX + 1]; |
83 | int used; | 83 | int used; |
84 | struct semaphore sem; | ||
84 | char phys[5][32]; | 85 | char phys[5][32]; |
85 | }; | 86 | }; |
86 | 87 | ||
@@ -433,7 +434,7 @@ static void gc_timer(unsigned long private) | |||
433 | gc_psx_read_packet(gc, data_psx, data); | 434 | gc_psx_read_packet(gc, data_psx, data); |
434 | 435 | ||
435 | for (i = 0; i < 5; i++) { | 436 | for (i = 0; i < 5; i++) { |
436 | switch (data[i]) { | 437 | switch (data[i]) { |
437 | 438 | ||
438 | case GC_PSX_RUMBLE: | 439 | case GC_PSX_RUMBLE: |
439 | 440 | ||
@@ -503,22 +504,33 @@ static void gc_timer(unsigned long private) | |||
503 | static int gc_open(struct input_dev *dev) | 504 | static int gc_open(struct input_dev *dev) |
504 | { | 505 | { |
505 | struct gc *gc = dev->private; | 506 | struct gc *gc = dev->private; |
507 | int err; | ||
508 | |||
509 | err = down_interruptible(&gc->sem); | ||
510 | if (err) | ||
511 | return err; | ||
512 | |||
506 | if (!gc->used++) { | 513 | if (!gc->used++) { |
507 | parport_claim(gc->pd); | 514 | parport_claim(gc->pd); |
508 | parport_write_control(gc->pd->port, 0x04); | 515 | parport_write_control(gc->pd->port, 0x04); |
509 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); | 516 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); |
510 | } | 517 | } |
518 | |||
519 | up(&gc->sem); | ||
511 | return 0; | 520 | return 0; |
512 | } | 521 | } |
513 | 522 | ||
514 | static void gc_close(struct input_dev *dev) | 523 | static void gc_close(struct input_dev *dev) |
515 | { | 524 | { |
516 | struct gc *gc = dev->private; | 525 | struct gc *gc = dev->private; |
526 | |||
527 | down(&gc->sem); | ||
517 | if (!--gc->used) { | 528 | if (!--gc->used) { |
518 | del_timer(&gc->timer); | 529 | del_timer_sync(&gc->timer); |
519 | parport_write_control(gc->pd->port, 0x00); | 530 | parport_write_control(gc->pd->port, 0x00); |
520 | parport_release(gc->pd); | 531 | parport_release(gc->pd); |
521 | } | 532 | } |
533 | up(&gc->sem); | ||
522 | } | 534 | } |
523 | 535 | ||
524 | static struct gc __init *gc_probe(int *config, int nargs) | 536 | static struct gc __init *gc_probe(int *config, int nargs) |
@@ -542,11 +554,12 @@ static struct gc __init *gc_probe(int *config, int nargs) | |||
542 | return NULL; | 554 | return NULL; |
543 | } | 555 | } |
544 | 556 | ||
545 | if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) { | 557 | if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) { |
546 | parport_put_port(pp); | 558 | parport_put_port(pp); |
547 | return NULL; | 559 | return NULL; |
548 | } | 560 | } |
549 | memset(gc, 0, sizeof(struct gc)); | 561 | |
562 | init_MUTEX(&gc->sem); | ||
550 | 563 | ||
551 | gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); | 564 | gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); |
552 | 565 | ||
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index ad13f09a4e71..7d969420066c 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c | |||
@@ -329,7 +329,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
329 | 329 | ||
330 | for (i = 0; i < gf2k_axes[gf2k->id]; i++) { | 330 | for (i = 0; i < gf2k_axes[gf2k->id]; i++) { |
331 | gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 : | 331 | gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 : |
332 | gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; | 332 | gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; |
333 | gf2k->dev.absmin[gf2k_abs[i]] = 32; | 333 | gf2k->dev.absmin[gf2k_abs[i]] = 32; |
334 | gf2k->dev.absfuzz[gf2k_abs[i]] = 8; | 334 | gf2k->dev.absfuzz[gf2k_abs[i]] = 8; |
335 | gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; | 335 | gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; |
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 42e5005d621f..0da7bd133ccf 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c | |||
@@ -171,7 +171,7 @@ static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *pa | |||
171 | *packet = 0; | 171 | *packet = 0; |
172 | raw_data = gameport_read(gameport); | 172 | raw_data = gameport_read(gameport); |
173 | if (raw_data & 1) | 173 | if (raw_data & 1) |
174 | return IO_RETRY; | 174 | return IO_RETRY; |
175 | 175 | ||
176 | for (i = 0; i < 64; i++) { | 176 | for (i = 0; i < 64; i++) { |
177 | raw_data = gameport_read(gameport); | 177 | raw_data = gameport_read(gameport); |
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 028f3513629a..e31b7b93fde2 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c | |||
@@ -78,6 +78,7 @@ static struct iforce_device iforce_device[] = { | |||
78 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? | 78 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? |
79 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? | 79 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? |
80 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? | 80 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? |
81 | { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? | ||
81 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } | 82 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } |
82 | }; | 83 | }; |
83 | 84 | ||
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 617c0b0e5a39..6369a24684fe 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c | |||
@@ -229,6 +229,7 @@ static struct usb_device_id iforce_usb_ids [] = { | |||
229 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ | 229 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ |
230 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ | 230 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ |
231 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ | 231 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ |
232 | { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ | ||
232 | { } /* Terminating entry */ | 233 | { } /* Terminating entry */ |
233 | }; | 234 | }; |
234 | 235 | ||
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index ec0a2a64d49c..a436f2220856 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c | |||
@@ -4,8 +4,8 @@ | |||
4 | * Copyright (c) 1999-2001 Vojtech Pavlik | 4 | * Copyright (c) 1999-2001 Vojtech Pavlik |
5 | * | 5 | * |
6 | * Based on the work of: | 6 | * Based on the work of: |
7 | * David Thompson | 7 | * David Thompson |
8 | * Joseph Krahn | 8 | * Joseph Krahn |
9 | */ | 9 | */ |
10 | 10 | ||
11 | /* | 11 | /* |
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index 874367bfab08..01fd2e4791ae 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (c) 1999-2001 Vojtech Pavlik | 4 | * Copyright (c) 1999-2001 Vojtech Pavlik |
5 | * | 5 | * |
6 | * Based on the work of: | 6 | * Based on the work of: |
7 | * David Thompson | 7 | * David Thompson |
8 | */ | 8 | */ |
9 | 9 | ||
10 | /* | 10 | /* |
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index aaee52ceb920..9eb9954cac6e 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c | |||
@@ -79,7 +79,7 @@ static short tmdc_btn_pad[TMDC_BTN] = | |||
79 | { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR }; | 79 | { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR }; |
80 | static short tmdc_btn_joy[TMDC_BTN] = | 80 | static short tmdc_btn_joy[TMDC_BTN] = |
81 | { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE, | 81 | { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE, |
82 | BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z }; | 82 | BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z }; |
83 | static short tmdc_btn_fm[TMDC_BTN] = | 83 | static short tmdc_btn_fm[TMDC_BTN] = |
84 | { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 }; | 84 | { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 }; |
85 | static short tmdc_btn_at[TMDC_BTN] = | 85 | static short tmdc_btn_at[TMDC_BTN] = |
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index dd88b9cb49fa..28100d461cb7 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c | |||
@@ -84,6 +84,7 @@ static struct tgfx { | |||
84 | char phys[7][32]; | 84 | char phys[7][32]; |
85 | int sticks; | 85 | int sticks; |
86 | int used; | 86 | int used; |
87 | struct semaphore sem; | ||
87 | } *tgfx_base[3]; | 88 | } *tgfx_base[3]; |
88 | 89 | ||
89 | /* | 90 | /* |
@@ -99,7 +100,7 @@ static void tgfx_timer(unsigned long private) | |||
99 | for (i = 0; i < 7; i++) | 100 | for (i = 0; i < 7; i++) |
100 | if (tgfx->sticks & (1 << i)) { | 101 | if (tgfx->sticks & (1 << i)) { |
101 | 102 | ||
102 | dev = tgfx->dev + i; | 103 | dev = tgfx->dev + i; |
103 | 104 | ||
104 | parport_write_data(tgfx->pd->port, ~(1 << i)); | 105 | parport_write_data(tgfx->pd->port, ~(1 << i)); |
105 | data1 = parport_read_status(tgfx->pd->port) ^ 0x7f; | 106 | data1 = parport_read_status(tgfx->pd->port) ^ 0x7f; |
@@ -122,23 +123,34 @@ static void tgfx_timer(unsigned long private) | |||
122 | 123 | ||
123 | static int tgfx_open(struct input_dev *dev) | 124 | static int tgfx_open(struct input_dev *dev) |
124 | { | 125 | { |
125 | struct tgfx *tgfx = dev->private; | 126 | struct tgfx *tgfx = dev->private; |
126 | if (!tgfx->used++) { | 127 | int err; |
128 | |||
129 | err = down_interruptible(&tgfx->sem); | ||
130 | if (err) | ||
131 | return err; | ||
132 | |||
133 | if (!tgfx->used++) { | ||
127 | parport_claim(tgfx->pd); | 134 | parport_claim(tgfx->pd); |
128 | parport_write_control(tgfx->pd->port, 0x04); | 135 | parport_write_control(tgfx->pd->port, 0x04); |
129 | mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); | 136 | mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); |
130 | } | 137 | } |
131 | return 0; | 138 | |
139 | up(&tgfx->sem); | ||
140 | return 0; | ||
132 | } | 141 | } |
133 | 142 | ||
134 | static void tgfx_close(struct input_dev *dev) | 143 | static void tgfx_close(struct input_dev *dev) |
135 | { | 144 | { |
136 | struct tgfx *tgfx = dev->private; | 145 | struct tgfx *tgfx = dev->private; |
137 | if (!--tgfx->used) { | 146 | |
138 | del_timer(&tgfx->timer); | 147 | down(&tgfx->sem); |
148 | if (!--tgfx->used) { | ||
149 | del_timer_sync(&tgfx->timer); | ||
139 | parport_write_control(tgfx->pd->port, 0x00); | 150 | parport_write_control(tgfx->pd->port, 0x00); |
140 | parport_release(tgfx->pd); | 151 | parport_release(tgfx->pd); |
141 | } | 152 | } |
153 | up(&tgfx->sem); | ||
142 | } | 154 | } |
143 | 155 | ||
144 | /* | 156 | /* |
@@ -166,11 +178,12 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs) | |||
166 | return NULL; | 178 | return NULL; |
167 | } | 179 | } |
168 | 180 | ||
169 | if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) { | 181 | if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) { |
170 | parport_put_port(pp); | 182 | parport_put_port(pp); |
171 | return NULL; | 183 | return NULL; |
172 | } | 184 | } |
173 | memset(tgfx, 0, sizeof(struct tgfx)); | 185 | |
186 | init_MUTEX(&tgfx->sem); | ||
174 | 187 | ||
175 | tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); | 188 | tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); |
176 | 189 | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 82fad9a23ace..4d4985b59abf 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -227,7 +227,7 @@ static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *a | |||
227 | { \ | 227 | { \ |
228 | return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ | 228 | return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ |
229 | } \ | 229 | } \ |
230 | static struct device_attribute atkbd_attr_##_name = \ | 230 | static struct device_attribute atkbd_attr_##_name = \ |
231 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); | 231 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); |
232 | 232 | ||
233 | ATKBD_DEFINE_ATTR(extra); | 233 | ATKBD_DEFINE_ATTR(extra); |
@@ -388,7 +388,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
388 | value = atkbd->release ? 0 : | 388 | value = atkbd->release ? 0 : |
389 | (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); | 389 | (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); |
390 | 390 | ||
391 | switch (value) { /* Workaround Toshiba laptop multiple keypress */ | 391 | switch (value) { /* Workaround Toshiba laptop multiple keypress */ |
392 | case 0: | 392 | case 0: |
393 | atkbd->last = 0; | 393 | atkbd->last = 0; |
394 | break; | 394 | break; |
@@ -894,7 +894,7 @@ static int atkbd_reconnect(struct serio *serio) | |||
894 | if (atkbd->write) { | 894 | if (atkbd->write) { |
895 | param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) | 895 | param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) |
896 | | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) | 896 | | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) |
897 | | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); | 897 | | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); |
898 | 898 | ||
899 | if (atkbd_probe(atkbd)) | 899 | if (atkbd_probe(atkbd)) |
900 | return -1; | 900 | return -1; |
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index 0f1220a0ceb5..a8551711e8d6 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #define CORGI_KEY_CALENDER KEY_F1 | 39 | #define CORGI_KEY_CALENDER KEY_F1 |
40 | #define CORGI_KEY_ADDRESS KEY_F2 | 40 | #define CORGI_KEY_ADDRESS KEY_F2 |
41 | #define CORGI_KEY_FN KEY_F3 | 41 | #define CORGI_KEY_FN KEY_F3 |
42 | #define CORGI_KEY_CANCEL KEY_F4 | ||
42 | #define CORGI_KEY_OFF KEY_SUSPEND | 43 | #define CORGI_KEY_OFF KEY_SUSPEND |
43 | #define CORGI_KEY_EXOK KEY_F5 | 44 | #define CORGI_KEY_EXOK KEY_F5 |
44 | #define CORGI_KEY_EXCANCEL KEY_F6 | 45 | #define CORGI_KEY_EXCANCEL KEY_F6 |
@@ -46,6 +47,7 @@ | |||
46 | #define CORGI_KEY_EXJOGUP KEY_F8 | 47 | #define CORGI_KEY_EXJOGUP KEY_F8 |
47 | #define CORGI_KEY_JAP1 KEY_LEFTCTRL | 48 | #define CORGI_KEY_JAP1 KEY_LEFTCTRL |
48 | #define CORGI_KEY_JAP2 KEY_LEFTALT | 49 | #define CORGI_KEY_JAP2 KEY_LEFTALT |
50 | #define CORGI_KEY_MAIL KEY_F10 | ||
49 | #define CORGI_KEY_OK KEY_F11 | 51 | #define CORGI_KEY_OK KEY_F11 |
50 | #define CORGI_KEY_MENU KEY_F12 | 52 | #define CORGI_KEY_MENU KEY_F12 |
51 | #define CORGI_HINGE_0 KEY_KP0 | 53 | #define CORGI_HINGE_0 KEY_KP0 |
@@ -59,8 +61,8 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = { | |||
59 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | 61 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ |
60 | CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ | 62 | CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ |
61 | CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ | 63 | CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ |
62 | KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ | 64 | CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ |
63 | KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ | 65 | KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ |
64 | CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ | 66 | CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ |
65 | CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */ | 67 | CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */ |
66 | }; | 68 | }; |
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 2694ff2b5beb..098963c7cdd6 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c | |||
@@ -15,10 +15,10 @@ | |||
15 | * information given below, I will _not_ be liable! | 15 | * information given below, I will _not_ be liable! |
16 | * | 16 | * |
17 | * RJ10 pinout: To DE9: Or DB25: | 17 | * RJ10 pinout: To DE9: Or DB25: |
18 | * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD) | 18 | * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD) |
19 | * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND) | 19 | * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND) |
20 | * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD) | 20 | * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD) |
21 | * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!! | 21 | * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!! |
22 | * | 22 | * |
23 | * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For | 23 | * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For |
24 | * RJ10, it's like this: | 24 | * RJ10, it's like this: |
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index d3e9dd6a13cd..8935290256b3 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c | |||
@@ -42,7 +42,7 @@ MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>"); | |||
42 | MODULE_DESCRIPTION("LoCoMo keyboard driver"); | 42 | MODULE_DESCRIPTION("LoCoMo keyboard driver"); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | 44 | ||
45 | #define LOCOMOKBD_NUMKEYS 128 | 45 | #define LOCOMOKBD_NUMKEYS 128 |
46 | 46 | ||
47 | #define KEY_ACTIVITY KEY_F16 | 47 | #define KEY_ACTIVITY KEY_F16 |
48 | #define KEY_CONTACT KEY_F18 | 48 | #define KEY_CONTACT KEY_F18 |
@@ -61,7 +61,7 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = { | |||
61 | KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */ | 61 | KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */ |
62 | 0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */ | 62 | 0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */ |
63 | KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */ | 63 | KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */ |
64 | KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */ | 64 | KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */ |
65 | }; | 65 | }; |
66 | 66 | ||
67 | #define KB_ROWS 16 | 67 | #define KB_ROWS 16 |
@@ -82,7 +82,7 @@ struct locomokbd { | |||
82 | struct locomo_dev *ldev; | 82 | struct locomo_dev *ldev; |
83 | unsigned long base; | 83 | unsigned long base; |
84 | spinlock_t lock; | 84 | spinlock_t lock; |
85 | 85 | ||
86 | struct timer_list timer; | 86 | struct timer_list timer; |
87 | }; | 87 | }; |
88 | 88 | ||
@@ -95,7 +95,7 @@ static inline void locomokbd_charge_all(unsigned long membase) | |||
95 | static inline void locomokbd_activate_all(unsigned long membase) | 95 | static inline void locomokbd_activate_all(unsigned long membase) |
96 | { | 96 | { |
97 | unsigned long r; | 97 | unsigned long r; |
98 | 98 | ||
99 | locomo_writel(0, membase + LOCOMO_KSC); | 99 | locomo_writel(0, membase + LOCOMO_KSC); |
100 | r = locomo_readl(membase + LOCOMO_KIC); | 100 | r = locomo_readl(membase + LOCOMO_KIC); |
101 | r &= 0xFEFF; | 101 | r &= 0xFEFF; |
@@ -127,7 +127,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col) | |||
127 | */ | 127 | */ |
128 | 128 | ||
129 | /* Scan the hardware keyboard and push any changes up through the input layer */ | 129 | /* Scan the hardware keyboard and push any changes up through the input layer */ |
130 | static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs) | 130 | static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs) |
131 | { | 131 | { |
132 | unsigned int row, col, rowd, scancode; | 132 | unsigned int row, col, rowd, scancode; |
133 | unsigned long flags; | 133 | unsigned long flags; |
@@ -138,7 +138,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * | |||
138 | 138 | ||
139 | if (regs) | 139 | if (regs) |
140 | input_regs(&locomokbd->input, regs); | 140 | input_regs(&locomokbd->input, regs); |
141 | 141 | ||
142 | locomokbd_charge_all(membase); | 142 | locomokbd_charge_all(membase); |
143 | 143 | ||
144 | num_pressed = 0; | 144 | num_pressed = 0; |
@@ -146,9 +146,9 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * | |||
146 | 146 | ||
147 | locomokbd_activate_col(membase, col); | 147 | locomokbd_activate_col(membase, col); |
148 | udelay(KB_DELAY); | 148 | udelay(KB_DELAY); |
149 | 149 | ||
150 | rowd = ~locomo_readl(membase + LOCOMO_KIB); | 150 | rowd = ~locomo_readl(membase + LOCOMO_KIB); |
151 | for (row = 0; row < KB_ROWS; row++ ) { | 151 | for (row = 0; row < KB_ROWS; row++) { |
152 | scancode = SCANCODE(col, row); | 152 | scancode = SCANCODE(col, row); |
153 | if (rowd & KB_ROWMASK(row)) { | 153 | if (rowd & KB_ROWMASK(row)) { |
154 | num_pressed += 1; | 154 | num_pressed += 1; |
@@ -170,7 +170,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * | |||
170 | spin_unlock_irqrestore(&locomokbd->lock, flags); | 170 | spin_unlock_irqrestore(&locomokbd->lock, flags); |
171 | } | 171 | } |
172 | 172 | ||
173 | /* | 173 | /* |
174 | * LoCoMo keyboard interrupt handler. | 174 | * LoCoMo keyboard interrupt handler. |
175 | */ | 175 | */ |
176 | static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 176 | static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
@@ -205,8 +205,8 @@ static int locomokbd_probe(struct locomo_dev *dev) | |||
205 | memset(locomokbd, 0, sizeof(struct locomokbd)); | 205 | memset(locomokbd, 0, sizeof(struct locomokbd)); |
206 | 206 | ||
207 | /* try and claim memory region */ | 207 | /* try and claim memory region */ |
208 | if (!request_mem_region((unsigned long) dev->mapbase, | 208 | if (!request_mem_region((unsigned long) dev->mapbase, |
209 | dev->length, | 209 | dev->length, |
210 | LOCOMO_DRIVER_NAME(dev))) { | 210 | LOCOMO_DRIVER_NAME(dev))) { |
211 | ret = -EBUSY; | 211 | ret = -EBUSY; |
212 | printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n"); | 212 | printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n"); |
@@ -225,7 +225,7 @@ static int locomokbd_probe(struct locomo_dev *dev) | |||
225 | locomokbd->timer.data = (unsigned long) locomokbd; | 225 | locomokbd->timer.data = (unsigned long) locomokbd; |
226 | 226 | ||
227 | locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | 227 | locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); |
228 | 228 | ||
229 | init_input_dev(&locomokbd->input); | 229 | init_input_dev(&locomokbd->input); |
230 | locomokbd->input.keycode = locomokbd->keycode; | 230 | locomokbd->input.keycode = locomokbd->keycode; |
231 | locomokbd->input.keycodesize = sizeof(unsigned char); | 231 | locomokbd->input.keycodesize = sizeof(unsigned char); |
@@ -271,11 +271,11 @@ free: | |||
271 | static int locomokbd_remove(struct locomo_dev *dev) | 271 | static int locomokbd_remove(struct locomo_dev *dev) |
272 | { | 272 | { |
273 | struct locomokbd *locomokbd = locomo_get_drvdata(dev); | 273 | struct locomokbd *locomokbd = locomo_get_drvdata(dev); |
274 | 274 | ||
275 | free_irq(dev->irq[0], locomokbd); | 275 | free_irq(dev->irq[0], locomokbd); |
276 | 276 | ||
277 | del_timer_sync(&locomokbd->timer); | 277 | del_timer_sync(&locomokbd->timer); |
278 | 278 | ||
279 | input_unregister_device(&locomokbd->input); | 279 | input_unregister_device(&locomokbd->input); |
280 | locomo_set_drvdata(dev, NULL); | 280 | locomo_set_drvdata(dev, NULL); |
281 | 281 | ||
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c index 859ed771ee0a..eecbde294f1f 100644 --- a/drivers/input/keyboard/maple_keyb.c +++ b/drivers/input/keyboard/maple_keyb.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $ | 2 | * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $ |
3 | * SEGA Dreamcast keyboard driver | 3 | * SEGA Dreamcast keyboard driver |
4 | * Based on drivers/usb/usbkbd.c | 4 | * Based on drivers/usb/usbkbd.c |
5 | */ | 5 | */ |
6 | 6 | ||
@@ -40,7 +40,6 @@ struct dc_kbd { | |||
40 | struct input_dev dev; | 40 | struct input_dev dev; |
41 | unsigned char new[8]; | 41 | unsigned char new[8]; |
42 | unsigned char old[8]; | 42 | unsigned char old[8]; |
43 | int open; | ||
44 | }; | 43 | }; |
45 | 44 | ||
46 | 45 | ||
@@ -95,22 +94,6 @@ static void dc_kbd_callback(struct mapleq *mq) | |||
95 | } | 94 | } |
96 | } | 95 | } |
97 | 96 | ||
98 | |||
99 | static int dc_kbd_open(struct input_dev *dev) | ||
100 | { | ||
101 | struct dc_kbd *kbd = dev->private; | ||
102 | kbd->open++; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | |||
107 | static void dc_kbd_close(struct input_dev *dev) | ||
108 | { | ||
109 | struct dc_kbd *kbd = dev->private; | ||
110 | kbd->open--; | ||
111 | } | ||
112 | |||
113 | |||
114 | static int dc_kbd_connect(struct maple_device *dev) | 97 | static int dc_kbd_connect(struct maple_device *dev) |
115 | { | 98 | { |
116 | int i; | 99 | int i; |
@@ -133,9 +116,6 @@ static int dc_kbd_connect(struct maple_device *dev) | |||
133 | clear_bit(0, kbd->dev.keybit); | 116 | clear_bit(0, kbd->dev.keybit); |
134 | 117 | ||
135 | kbd->dev.private = kbd; | 118 | kbd->dev.private = kbd; |
136 | kbd->dev.open = dc_kbd_open; | ||
137 | kbd->dev.close = dc_kbd_close; | ||
138 | kbd->dev.event = NULL; | ||
139 | 119 | ||
140 | kbd->dev.name = dev->product_name; | 120 | kbd->dev.name = dev->product_name; |
141 | kbd->dev.id.bustype = BUS_MAPLE; | 121 | kbd->dev.id.bustype = BUS_MAPLE; |
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 158c8e845ff9..98710997aaaa 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
@@ -298,9 +298,11 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz | |||
298 | /* check if absmin/absmax/absfuzz/absflat are filled as | 298 | /* check if absmin/absmax/absfuzz/absflat are filled as |
299 | * told in Documentation/input/input-programming.txt */ | 299 | * told in Documentation/input/input-programming.txt */ |
300 | if (test_bit(EV_ABS, dev->evbit)) { | 300 | if (test_bit(EV_ABS, dev->evbit)) { |
301 | retval = uinput_validate_absbits(dev); | 301 | int err = uinput_validate_absbits(dev); |
302 | if (retval < 0) | 302 | if (err < 0) { |
303 | retval = err; | ||
303 | kfree(dev->name); | 304 | kfree(dev->name); |
305 | } | ||
304 | } | 306 | } |
305 | 307 | ||
306 | exit: | 308 | exit: |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index a7864195806a..c4909b49337d 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o | |||
15 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o | 15 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o |
16 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o | 16 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o |
17 | 17 | ||
18 | psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o | 18 | psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 7bf4be733e9a..a12e98158a75 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -30,10 +30,11 @@ | |||
30 | 30 | ||
31 | #define ALPS_DUALPOINT 0x01 | 31 | #define ALPS_DUALPOINT 0x01 |
32 | #define ALPS_WHEEL 0x02 | 32 | #define ALPS_WHEEL 0x02 |
33 | #define ALPS_FW_BK 0x04 | 33 | #define ALPS_FW_BK_1 0x04 |
34 | #define ALPS_4BTN 0x08 | 34 | #define ALPS_4BTN 0x08 |
35 | #define ALPS_OLDPROTO 0x10 | 35 | #define ALPS_OLDPROTO 0x10 |
36 | #define ALPS_PASS 0x20 | 36 | #define ALPS_PASS 0x20 |
37 | #define ALPS_FW_BK_2 0x40 | ||
37 | 38 | ||
38 | static struct alps_model_info alps_model_data[] = { | 39 | static struct alps_model_info alps_model_data[] = { |
39 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ | 40 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ |
@@ -43,11 +44,11 @@ static struct alps_model_info alps_model_data[] = { | |||
43 | { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, | 44 | { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, |
44 | { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 }, | 45 | { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 }, |
45 | { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ | 46 | { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ |
46 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK }, /* NEC Versa L320 */ | 47 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ |
47 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, | 48 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, |
48 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ | 49 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ |
49 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, | 50 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, |
50 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, | 51 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ |
51 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 52 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
52 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 53 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
53 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 54 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
@@ -61,11 +62,11 @@ static struct alps_model_info alps_model_data[] = { | |||
61 | 62 | ||
62 | /* | 63 | /* |
63 | * ALPS abolute Mode - new format | 64 | * ALPS abolute Mode - new format |
64 | * | 65 | * |
65 | * byte 0: 1 ? ? ? 1 ? ? ? | 66 | * byte 0: 1 ? ? ? 1 ? ? ? |
66 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | 67 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 |
67 | * byte 2: 0 x10 x9 x8 x7 ? fin ges | 68 | * byte 2: 0 x10 x9 x8 x7 ? fin ges |
68 | * byte 3: 0 y9 y8 y7 1 M R L | 69 | * byte 3: 0 y9 y8 y7 1 M R L |
69 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 | 70 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 |
70 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 | 71 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 |
71 | * | 72 | * |
@@ -81,11 +82,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) | |||
81 | struct input_dev *dev = &psmouse->dev; | 82 | struct input_dev *dev = &psmouse->dev; |
82 | struct input_dev *dev2 = &priv->dev2; | 83 | struct input_dev *dev2 = &priv->dev2; |
83 | int x, y, z, ges, fin, left, right, middle; | 84 | int x, y, z, ges, fin, left, right, middle; |
85 | int back = 0, forward = 0; | ||
84 | 86 | ||
85 | input_regs(dev, regs); | 87 | input_regs(dev, regs); |
86 | 88 | ||
87 | if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ | 89 | if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ |
88 | input_report_key(dev2, BTN_LEFT, packet[0] & 1); | 90 | input_report_key(dev2, BTN_LEFT, packet[0] & 1); |
89 | input_report_key(dev2, BTN_RIGHT, packet[0] & 2); | 91 | input_report_key(dev2, BTN_RIGHT, packet[0] & 2); |
90 | input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); | 92 | input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); |
91 | input_report_rel(dev2, REL_X, | 93 | input_report_rel(dev2, REL_X, |
@@ -112,6 +114,18 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) | |||
112 | z = packet[5]; | 114 | z = packet[5]; |
113 | } | 115 | } |
114 | 116 | ||
117 | if (priv->i->flags & ALPS_FW_BK_1) { | ||
118 | back = packet[2] & 4; | ||
119 | forward = packet[0] & 0x10; | ||
120 | } | ||
121 | |||
122 | if (priv->i->flags & ALPS_FW_BK_2) { | ||
123 | back = packet[3] & 4; | ||
124 | forward = packet[2] & 4; | ||
125 | if ((middle = forward && back)) | ||
126 | forward = back = 0; | ||
127 | } | ||
128 | |||
115 | ges = packet[2] & 1; | 129 | ges = packet[2] & 1; |
116 | fin = packet[2] & 2; | 130 | fin = packet[2] & 2; |
117 | 131 | ||
@@ -155,13 +169,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) | |||
155 | input_report_abs(dev, ABS_PRESSURE, z); | 169 | input_report_abs(dev, ABS_PRESSURE, z); |
156 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); | 170 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); |
157 | 171 | ||
158 | |||
159 | if (priv->i->flags & ALPS_WHEEL) | 172 | if (priv->i->flags & ALPS_WHEEL) |
160 | input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08)); | 173 | input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08)); |
161 | 174 | ||
162 | if (priv->i->flags & ALPS_FW_BK) { | 175 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
163 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x10); | 176 | input_report_key(dev, BTN_FORWARD, forward); |
164 | input_report_key(dev, BTN_BACK, packet[2] & 0x04); | 177 | input_report_key(dev, BTN_BACK, back); |
165 | } | 178 | } |
166 | 179 | ||
167 | input_sync(dev); | 180 | input_sync(dev); |
@@ -257,7 +270,6 @@ static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *vers | |||
257 | static int alps_passthrough_mode(struct psmouse *psmouse, int enable) | 270 | static int alps_passthrough_mode(struct psmouse *psmouse, int enable) |
258 | { | 271 | { |
259 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 272 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
260 | unsigned char param[3]; | ||
261 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; | 273 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; |
262 | 274 | ||
263 | if (ps2_command(ps2dev, NULL, cmd) || | 275 | if (ps2_command(ps2dev, NULL, cmd) || |
@@ -267,7 +279,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, int enable) | |||
267 | return -1; | 279 | return -1; |
268 | 280 | ||
269 | /* we may get 3 more bytes, just ignore them */ | 281 | /* we may get 3 more bytes, just ignore them */ |
270 | ps2_command(ps2dev, param, 0x0300); | 282 | ps2_drain(ps2dev, 3, 100); |
271 | 283 | ||
272 | return 0; | 284 | return 0; |
273 | } | 285 | } |
@@ -425,7 +437,7 @@ int alps_init(struct psmouse *psmouse) | |||
425 | psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL); | 437 | psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL); |
426 | } | 438 | } |
427 | 439 | ||
428 | if (priv->i->flags & ALPS_FW_BK) { | 440 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
429 | psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD); | 441 | psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD); |
430 | psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); | 442 | psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); |
431 | } | 443 | } |
@@ -436,8 +448,8 @@ int alps_init(struct psmouse *psmouse) | |||
436 | priv->dev2.id.bustype = BUS_I8042; | 448 | priv->dev2.id.bustype = BUS_I8042; |
437 | priv->dev2.id.vendor = 0x0002; | 449 | priv->dev2.id.vendor = 0x0002; |
438 | priv->dev2.id.product = PSMOUSE_ALPS; | 450 | priv->dev2.id.product = PSMOUSE_ALPS; |
439 | priv->dev2.id.version = 0x0000; | 451 | priv->dev2.id.version = 0x0000; |
440 | 452 | ||
441 | priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 453 | priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); |
442 | priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y); | 454 | priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y); |
443 | priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | 455 | priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); |
@@ -461,17 +473,15 @@ init_fail: | |||
461 | int alps_detect(struct psmouse *psmouse, int set_properties) | 473 | int alps_detect(struct psmouse *psmouse, int set_properties) |
462 | { | 474 | { |
463 | int version; | 475 | int version; |
464 | struct alps_model_info *model; | 476 | struct alps_model_info *model; |
465 | 477 | ||
466 | if (!(model = alps_get_model(psmouse, &version))) | 478 | if (!(model = alps_get_model(psmouse, &version))) |
467 | return -1; | 479 | return -1; |
468 | 480 | ||
469 | if (set_properties) { | 481 | if (set_properties) { |
470 | psmouse->vendor = "ALPS"; | 482 | psmouse->vendor = "ALPS"; |
471 | if (model->flags & ALPS_DUALPOINT) | 483 | psmouse->name = model->flags & ALPS_DUALPOINT ? |
472 | psmouse->name = "DualPoint TouchPad"; | 484 | "DualPoint TouchPad" : "GlidePoint"; |
473 | else | ||
474 | psmouse->name = "GlidePoint"; | ||
475 | psmouse->model = version; | 485 | psmouse->model = version; |
476 | } | 486 | } |
477 | return 0; | 487 | return 0; |
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c index 7baa09cca7c5..e994849efb8f 100644 --- a/drivers/input/mouse/amimouse.c +++ b/drivers/input/mouse/amimouse.c | |||
@@ -33,7 +33,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |||
33 | MODULE_DESCRIPTION("Amiga mouse driver"); | 33 | MODULE_DESCRIPTION("Amiga mouse driver"); |
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | 35 | ||
36 | static int amimouse_used = 0; | ||
37 | static int amimouse_lastx, amimouse_lasty; | 36 | static int amimouse_lastx, amimouse_lasty; |
38 | static struct input_dev amimouse_dev; | 37 | static struct input_dev amimouse_dev; |
39 | 38 | ||
@@ -81,16 +80,12 @@ static int amimouse_open(struct input_dev *dev) | |||
81 | { | 80 | { |
82 | unsigned short joy0dat; | 81 | unsigned short joy0dat; |
83 | 82 | ||
84 | if (amimouse_used++) | ||
85 | return 0; | ||
86 | |||
87 | joy0dat = custom.joy0dat; | 83 | joy0dat = custom.joy0dat; |
88 | 84 | ||
89 | amimouse_lastx = joy0dat & 0xff; | 85 | amimouse_lastx = joy0dat & 0xff; |
90 | amimouse_lasty = joy0dat >> 8; | 86 | amimouse_lasty = joy0dat >> 8; |
91 | 87 | ||
92 | if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) { | 88 | if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) { |
93 | amimouse_used--; | ||
94 | printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); | 89 | printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); |
95 | return -EBUSY; | 90 | return -EBUSY; |
96 | } | 91 | } |
@@ -100,8 +95,7 @@ static int amimouse_open(struct input_dev *dev) | |||
100 | 95 | ||
101 | static void amimouse_close(struct input_dev *dev) | 96 | static void amimouse_close(struct input_dev *dev) |
102 | { | 97 | { |
103 | if (!--amimouse_used) | 98 | free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt); |
104 | free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt); | ||
105 | } | 99 | } |
106 | 100 | ||
107 | static int __init amimouse_init(void) | 101 | static int __init amimouse_init(void) |
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c index ca4e96886627..1f62c0134010 100644 --- a/drivers/input/mouse/inport.c +++ b/drivers/input/mouse/inport.c | |||
@@ -17,18 +17,18 @@ | |||
17 | /* | 17 | /* |
18 | * This program is free software; you can redistribute it and/or modify | 18 | * This program is free software; you can redistribute it and/or modify |
19 | * it under the terms of the GNU General Public License as published by | 19 | * it under the terms of the GNU General Public License as published by |
20 | * the Free Software Foundation; either version 2 of the License, or | 20 | * the Free Software Foundation; either version 2 of the License, or |
21 | * (at your option) any later version. | 21 | * (at your option) any later version. |
22 | * | 22 | * |
23 | * This program is distributed in the hope that it will be useful, | 23 | * This program is distributed in the hope that it will be useful, |
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
26 | * GNU General Public License for more details. | 26 | * GNU General Public License for more details. |
27 | * | 27 | * |
28 | * You should have received a copy of the GNU General Public License | 28 | * You should have received a copy of the GNU General Public License |
29 | * along with this program; if not, write to the Free Software | 29 | * along with this program; if not, write to the Free Software |
30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
31 | * | 31 | * |
32 | * Should you need to contact me, the author, you can do so either by | 32 | * Should you need to contact me, the author, you can do so either by |
33 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 33 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
34 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 34 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
@@ -87,29 +87,23 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)"); | |||
87 | 87 | ||
88 | __obsolete_setup("inport_irq="); | 88 | __obsolete_setup("inport_irq="); |
89 | 89 | ||
90 | static int inport_used; | ||
91 | |||
92 | static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 90 | static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
93 | 91 | ||
94 | static int inport_open(struct input_dev *dev) | 92 | static int inport_open(struct input_dev *dev) |
95 | { | 93 | { |
96 | if (!inport_used++) { | 94 | if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL)) |
97 | if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL)) | 95 | return -EBUSY; |
98 | return -EBUSY; | 96 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); |
99 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); | 97 | outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); |
100 | outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); | ||
101 | } | ||
102 | 98 | ||
103 | return 0; | 99 | return 0; |
104 | } | 100 | } |
105 | 101 | ||
106 | static void inport_close(struct input_dev *dev) | 102 | static void inport_close(struct input_dev *dev) |
107 | { | 103 | { |
108 | if (!--inport_used) { | 104 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); |
109 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); | 105 | outb(INPORT_MODE_BASE, INPORT_DATA_PORT); |
110 | outb(INPORT_MODE_BASE, INPORT_DATA_PORT); | 106 | free_irq(inport_irq, NULL); |
111 | free_irq(inport_irq, NULL); | ||
112 | } | ||
113 | } | 107 | } |
114 | 108 | ||
115 | static struct input_dev inport_dev = { | 109 | static struct input_dev inport_dev = { |
@@ -120,11 +114,11 @@ static struct input_dev inport_dev = { | |||
120 | .close = inport_close, | 114 | .close = inport_close, |
121 | .name = INPORT_NAME, | 115 | .name = INPORT_NAME, |
122 | .phys = "isa023c/input0", | 116 | .phys = "isa023c/input0", |
123 | .id = { | 117 | .id = { |
124 | .bustype = BUS_ISA, | 118 | .bustype = BUS_ISA, |
125 | .vendor = INPORT_VENDOR, | 119 | .vendor = INPORT_VENDOR, |
126 | .product = 0x0001, | 120 | .product = 0x0001, |
127 | .version = 0x0100, | 121 | .version = 0x0100, |
128 | }, | 122 | }, |
129 | }; | 123 | }; |
130 | 124 | ||
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c new file mode 100644 index 000000000000..bd9df9b28325 --- /dev/null +++ b/drivers/input/mouse/lifebook.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Fujitsu B-series Lifebook PS/2 TouchScreen driver | ||
3 | * | ||
4 | * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> | ||
5 | * Copyright (c) 2005 Kenan Esau <kenan.esau@conan.de> | ||
6 | * | ||
7 | * TouchScreen detection, absolute mode setting and packet layout is taken from | ||
8 | * Harald Hoyer's description of the device. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License version 2 as published by | ||
12 | * the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/input.h> | ||
16 | #include <linux/serio.h> | ||
17 | #include <linux/libps2.h> | ||
18 | #include <linux/dmi.h> | ||
19 | |||
20 | #include "psmouse.h" | ||
21 | #include "lifebook.h" | ||
22 | |||
23 | static struct dmi_system_id lifebook_dmi_table[] = { | ||
24 | { | ||
25 | .ident = "Lifebook B", | ||
26 | .matches = { | ||
27 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), | ||
28 | }, | ||
29 | }, | ||
30 | { } | ||
31 | }; | ||
32 | |||
33 | |||
34 | static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs) | ||
35 | { | ||
36 | unsigned char *packet = psmouse->packet; | ||
37 | struct input_dev *dev = &psmouse->dev; | ||
38 | |||
39 | if (psmouse->pktcnt != 3) | ||
40 | return PSMOUSE_GOOD_DATA; | ||
41 | |||
42 | input_regs(dev, regs); | ||
43 | |||
44 | /* calculate X and Y */ | ||
45 | if ((packet[0] & 0x08) == 0x00) { | ||
46 | input_report_abs(dev, ABS_X, | ||
47 | (packet[1] | ((packet[0] & 0x30) << 4))); | ||
48 | input_report_abs(dev, ABS_Y, | ||
49 | 1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); | ||
50 | } else { | ||
51 | input_report_rel(dev, REL_X, | ||
52 | ((packet[0] & 0x10) ? packet[1] - 256 : packet[1])); | ||
53 | input_report_rel(dev, REL_Y, | ||
54 | -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2])); | ||
55 | } | ||
56 | |||
57 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | ||
58 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | ||
59 | input_report_key(dev, BTN_TOUCH, packet[0] & 0x04); | ||
60 | |||
61 | input_sync(dev); | ||
62 | |||
63 | return PSMOUSE_FULL_PACKET; | ||
64 | } | ||
65 | |||
66 | static int lifebook_absolute_mode(struct psmouse *psmouse) | ||
67 | { | ||
68 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
69 | unsigned char param; | ||
70 | |||
71 | if (psmouse_reset(psmouse)) | ||
72 | return -1; | ||
73 | |||
74 | /* | ||
75 | Enable absolute output -- ps2_command fails always but if | ||
76 | you leave this call out the touchsreen will never send | ||
77 | absolute coordinates | ||
78 | */ | ||
79 | param = 0x07; | ||
80 | ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution) | ||
86 | { | ||
87 | unsigned char params[] = { 0, 1, 2, 2, 3 }; | ||
88 | |||
89 | if (resolution == 0 || resolution > 400) | ||
90 | resolution = 400; | ||
91 | |||
92 | ps2_command(&psmouse->ps2dev, ¶ms[resolution / 100], PSMOUSE_CMD_SETRES); | ||
93 | psmouse->resolution = 50 << params[resolution / 100]; | ||
94 | } | ||
95 | |||
96 | static void lifebook_disconnect(struct psmouse *psmouse) | ||
97 | { | ||
98 | psmouse_reset(psmouse); | ||
99 | } | ||
100 | |||
101 | int lifebook_detect(struct psmouse *psmouse, int set_properties) | ||
102 | { | ||
103 | if (!dmi_check_system(lifebook_dmi_table)) | ||
104 | return -1; | ||
105 | |||
106 | if (set_properties) { | ||
107 | psmouse->vendor = "Fujitsu"; | ||
108 | psmouse->name = "Lifebook TouchScreen"; | ||
109 | } | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | int lifebook_init(struct psmouse *psmouse) | ||
115 | { | ||
116 | if (lifebook_absolute_mode(psmouse)) | ||
117 | return -1; | ||
118 | |||
119 | psmouse->dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL); | ||
120 | psmouse->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
121 | psmouse->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
122 | psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
123 | input_set_abs_params(&psmouse->dev, ABS_X, 0, 1024, 0, 0); | ||
124 | input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1024, 0, 0); | ||
125 | |||
126 | psmouse->protocol_handler = lifebook_process_byte; | ||
127 | psmouse->set_resolution = lifebook_set_resolution; | ||
128 | psmouse->disconnect = lifebook_disconnect; | ||
129 | psmouse->reconnect = lifebook_absolute_mode; | ||
130 | psmouse->pktsize = 3; | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
diff --git a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h new file mode 100644 index 000000000000..be1c0943825d --- /dev/null +++ b/drivers/input/mouse/lifebook.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * Fujitsu B-series Lifebook PS/2 TouchScreen driver | ||
3 | * | ||
4 | * Copyright (c) 2005 Vojtech Pavlik | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef _LIFEBOOK_H | ||
12 | #define _LIFEBOOK_H | ||
13 | |||
14 | int lifebook_detect(struct psmouse *psmouse, int set_properties); | ||
15 | int lifebook_init(struct psmouse *psmouse); | ||
16 | |||
17 | #endif | ||
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c index 77eb83e87f61..8b5243167227 100644 --- a/drivers/input/mouse/logibm.c +++ b/drivers/input/mouse/logibm.c | |||
@@ -18,18 +18,18 @@ | |||
18 | /* | 18 | /* |
19 | * This program is free software; you can redistribute it and/or modify | 19 | * This program is free software; you can redistribute it and/or modify |
20 | * it under the terms of the GNU General Public License as published by | 20 | * it under the terms of the GNU General Public License as published by |
21 | * the Free Software Foundation; either version 2 of the License, or | 21 | * the Free Software Foundation; either version 2 of the License, or |
22 | * (at your option) any later version. | 22 | * (at your option) any later version. |
23 | * | 23 | * |
24 | * This program is distributed in the hope that it will be useful, | 24 | * This program is distributed in the hope that it will be useful, |
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
27 | * GNU General Public License for more details. | 27 | * GNU General Public License for more details. |
28 | * | 28 | * |
29 | * You should have received a copy of the GNU General Public License | 29 | * You should have received a copy of the GNU General Public License |
30 | * along with this program; if not, write to the Free Software | 30 | * along with this program; if not, write to the Free Software |
31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
32 | * | 32 | * |
33 | * Should you need to contact me, the author, you can do so either by | 33 | * Should you need to contact me, the author, you can do so either by |
34 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 34 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
35 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 35 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
@@ -77,16 +77,11 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)"); | |||
77 | 77 | ||
78 | __obsolete_setup("logibm_irq="); | 78 | __obsolete_setup("logibm_irq="); |
79 | 79 | ||
80 | static int logibm_used = 0; | ||
81 | |||
82 | static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 80 | static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
83 | 81 | ||
84 | static int logibm_open(struct input_dev *dev) | 82 | static int logibm_open(struct input_dev *dev) |
85 | { | 83 | { |
86 | if (logibm_used++) | ||
87 | return 0; | ||
88 | if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) { | 84 | if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) { |
89 | logibm_used--; | ||
90 | printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq); | 85 | printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq); |
91 | return -EBUSY; | 86 | return -EBUSY; |
92 | } | 87 | } |
@@ -96,8 +91,6 @@ static int logibm_open(struct input_dev *dev) | |||
96 | 91 | ||
97 | static void logibm_close(struct input_dev *dev) | 92 | static void logibm_close(struct input_dev *dev) |
98 | { | 93 | { |
99 | if (--logibm_used) | ||
100 | return; | ||
101 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); | 94 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); |
102 | free_irq(logibm_irq, NULL); | 95 | free_irq(logibm_irq, NULL); |
103 | } | 96 | } |
@@ -167,7 +160,7 @@ static int __init logibm_init(void) | |||
167 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); | 160 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); |
168 | 161 | ||
169 | input_register_device(&logibm_dev); | 162 | input_register_device(&logibm_dev); |
170 | 163 | ||
171 | printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq); | 164 | printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq); |
172 | 165 | ||
173 | return 0; | 166 | return 0; |
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c index 12dc0ef5020f..e90c60cbbf05 100644 --- a/drivers/input/mouse/maplemouse.c +++ b/drivers/input/mouse/maplemouse.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $ | 2 | * $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $ |
3 | * SEGA Dreamcast mouse driver | 3 | * SEGA Dreamcast mouse driver |
4 | * Based on drivers/usb/usbmouse.c | 4 | * Based on drivers/usb/usbmouse.c |
5 | */ | 5 | */ |
6 | 6 | ||
@@ -15,80 +15,51 @@ | |||
15 | MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>"); | 15 | MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>"); |
16 | MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); | 16 | MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); |
17 | 17 | ||
18 | struct dc_mouse { | ||
19 | struct input_dev dev; | ||
20 | int open; | ||
21 | }; | ||
22 | |||
23 | |||
24 | static void dc_mouse_callback(struct mapleq *mq) | 18 | static void dc_mouse_callback(struct mapleq *mq) |
25 | { | 19 | { |
26 | int buttons, relx, rely, relz; | 20 | int buttons, relx, rely, relz; |
27 | struct maple_device *mapledev = mq->dev; | 21 | struct maple_device *mapledev = mq->dev; |
28 | struct dc_mouse *mouse = mapledev->private_data; | 22 | struct input_dev *dev = mapledev->private_data; |
29 | struct input_dev *dev = &mouse->dev; | ||
30 | unsigned char *res = mq->recvbuf; | 23 | unsigned char *res = mq->recvbuf; |
31 | 24 | ||
32 | buttons = ~res[8]; | 25 | buttons = ~res[8]; |
33 | relx=*(unsigned short *)(res+12)-512; | 26 | relx = *(unsigned short *)(res + 12) - 512; |
34 | rely=*(unsigned short *)(res+14)-512; | 27 | rely = *(unsigned short *)(res + 14) - 512; |
35 | relz=*(unsigned short *)(res+16)-512; | 28 | relz = *(unsigned short *)(res + 16) - 512; |
36 | 29 | ||
37 | input_report_key(dev, BTN_LEFT, buttons&4); | 30 | input_report_key(dev, BTN_LEFT, buttons & 4); |
38 | input_report_key(dev, BTN_MIDDLE, buttons&9); | 31 | input_report_key(dev, BTN_MIDDLE, buttons & 9); |
39 | input_report_key(dev, BTN_RIGHT, buttons&2); | 32 | input_report_key(dev, BTN_RIGHT, buttons & 2); |
40 | input_report_rel(dev, REL_X, relx); | 33 | input_report_rel(dev, REL_X, relx); |
41 | input_report_rel(dev, REL_Y, rely); | 34 | input_report_rel(dev, REL_Y, rely); |
42 | input_report_rel(dev, REL_WHEEL, relz); | 35 | input_report_rel(dev, REL_WHEEL, relz); |
43 | input_sync(dev); | 36 | input_sync(dev); |
44 | } | 37 | } |
45 | 38 | ||
46 | |||
47 | static int dc_mouse_open(struct input_dev *dev) | ||
48 | { | ||
49 | struct dc_mouse *mouse = dev->private; | ||
50 | mouse->open++; | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | |||
55 | static void dc_mouse_close(struct input_dev *dev) | ||
56 | { | ||
57 | struct dc_mouse *mouse = dev->private; | ||
58 | mouse->open--; | ||
59 | } | ||
60 | |||
61 | |||
62 | static int dc_mouse_connect(struct maple_device *dev) | 39 | static int dc_mouse_connect(struct maple_device *dev) |
63 | { | 40 | { |
64 | unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); | 41 | unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); |
65 | struct dc_mouse *mouse; | 42 | struct input_dev *input_dev; |
66 | 43 | ||
67 | if (!(mouse = kmalloc(sizeof(struct dc_mouse), GFP_KERNEL))) | 44 | if (!(input_dev = kmalloc(sizeof(struct input_dev), GFP_KERNEL))) |
68 | return -1; | 45 | return -1; |
69 | memset(mouse, 0, sizeof(struct dc_mouse)); | ||
70 | |||
71 | dev->private_data = mouse; | ||
72 | 46 | ||
73 | mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 47 | dev->private_data = input_dev; |
74 | mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
75 | mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); | ||
76 | 48 | ||
77 | init_input_dev(&mouse->dev); | 49 | memset(input_dev, 0, sizeof(struct dc_mouse)); |
50 | init_input_dev(input_dev); | ||
51 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
52 | input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
53 | input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); | ||
78 | 54 | ||
79 | mouse->dev.private = mouse; | 55 | input_dev->name = dev->product_name; |
80 | mouse->dev.open = dc_mouse_open; | 56 | input_dev->id.bustype = BUS_MAPLE; |
81 | mouse->dev.close = dc_mouse_close; | ||
82 | mouse->dev.event = NULL; | ||
83 | 57 | ||
84 | mouse->dev.name = dev->product_name; | 58 | input_register_device(input_dev); |
85 | mouse->dev.id.bustype = BUS_MAPLE; | ||
86 | |||
87 | input_register_device(&mouse->dev); | ||
88 | 59 | ||
89 | maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE); | 60 | maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE); |
90 | 61 | ||
91 | printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, mouse->dev.name); | 62 | printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, input_dev->name); |
92 | 63 | ||
93 | return 0; | 64 | return 0; |
94 | } | 65 | } |
@@ -96,10 +67,10 @@ static int dc_mouse_connect(struct maple_device *dev) | |||
96 | 67 | ||
97 | static void dc_mouse_disconnect(struct maple_device *dev) | 68 | static void dc_mouse_disconnect(struct maple_device *dev) |
98 | { | 69 | { |
99 | struct dc_mouse *mouse = dev->private_data; | 70 | struct input_dev *input_dev = dev->private_data; |
100 | 71 | ||
101 | input_unregister_device(&mouse->dev); | 72 | input_unregister_device(input_dev); |
102 | kfree(mouse); | 73 | kfree(input_dev); |
103 | } | 74 | } |
104 | 75 | ||
105 | 76 | ||
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index 0c74918fe254..93393d5c0078 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (c) 2000-2001 Vojtech Pavlik | 4 | * Copyright (c) 2000-2001 Vojtech Pavlik |
5 | * | 5 | * |
6 | * Based on the work of: | 6 | * Based on the work of: |
7 | * Alan Cox Robin O'Leary | 7 | * Alan Cox Robin O'Leary |
8 | */ | 8 | */ |
9 | 9 | ||
10 | /* | 10 | /* |
@@ -56,7 +56,6 @@ static int pc110pad_io = 0x15e0; | |||
56 | static struct input_dev pc110pad_dev; | 56 | static struct input_dev pc110pad_dev; |
57 | static int pc110pad_data[3]; | 57 | static int pc110pad_data[3]; |
58 | static int pc110pad_count; | 58 | static int pc110pad_count; |
59 | static int pc110pad_used; | ||
60 | 59 | ||
61 | static char *pc110pad_name = "IBM PC110 TouchPad"; | 60 | static char *pc110pad_name = "IBM PC110 TouchPad"; |
62 | static char *pc110pad_phys = "isa15e0/input0"; | 61 | static char *pc110pad_phys = "isa15e0/input0"; |
@@ -74,7 +73,7 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) | |||
74 | 73 | ||
75 | if (pc110pad_count < 3) | 74 | if (pc110pad_count < 3) |
76 | return IRQ_HANDLED; | 75 | return IRQ_HANDLED; |
77 | 76 | ||
78 | input_regs(&pc110pad_dev, regs); | 77 | input_regs(&pc110pad_dev, regs); |
79 | input_report_key(&pc110pad_dev, BTN_TOUCH, | 78 | input_report_key(&pc110pad_dev, BTN_TOUCH, |
80 | pc110pad_data[0] & 0x01); | 79 | pc110pad_data[0] & 0x01); |
@@ -90,15 +89,11 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) | |||
90 | 89 | ||
91 | static void pc110pad_close(struct input_dev *dev) | 90 | static void pc110pad_close(struct input_dev *dev) |
92 | { | 91 | { |
93 | if (!--pc110pad_used) | 92 | outb(PC110PAD_OFF, pc110pad_io + 2); |
94 | outb(PC110PAD_OFF, pc110pad_io + 2); | ||
95 | } | 93 | } |
96 | 94 | ||
97 | static int pc110pad_open(struct input_dev *dev) | 95 | static int pc110pad_open(struct input_dev *dev) |
98 | { | 96 | { |
99 | if (pc110pad_used++) | ||
100 | return 0; | ||
101 | |||
102 | pc110pad_interrupt(0,NULL,NULL); | 97 | pc110pad_interrupt(0,NULL,NULL); |
103 | pc110pad_interrupt(0,NULL,NULL); | 98 | pc110pad_interrupt(0,NULL,NULL); |
104 | pc110pad_interrupt(0,NULL,NULL); | 99 | pc110pad_interrupt(0,NULL,NULL); |
@@ -145,7 +140,7 @@ static int __init pc110pad_init(void) | |||
145 | 140 | ||
146 | pc110pad_dev.absmax[ABS_X] = 0x1ff; | 141 | pc110pad_dev.absmax[ABS_X] = 0x1ff; |
147 | pc110pad_dev.absmax[ABS_Y] = 0x0ff; | 142 | pc110pad_dev.absmax[ABS_Y] = 0x0ff; |
148 | 143 | ||
149 | pc110pad_dev.open = pc110pad_open; | 144 | pc110pad_dev.open = pc110pad_open; |
150 | pc110pad_dev.close = pc110pad_close; | 145 | pc110pad_dev.close = pc110pad_close; |
151 | 146 | ||
@@ -156,17 +151,17 @@ static int __init pc110pad_init(void) | |||
156 | pc110pad_dev.id.product = 0x0001; | 151 | pc110pad_dev.id.product = 0x0001; |
157 | pc110pad_dev.id.version = 0x0100; | 152 | pc110pad_dev.id.version = 0x0100; |
158 | 153 | ||
159 | input_register_device(&pc110pad_dev); | 154 | input_register_device(&pc110pad_dev); |
160 | 155 | ||
161 | printk(KERN_INFO "input: %s at %#x irq %d\n", | 156 | printk(KERN_INFO "input: %s at %#x irq %d\n", |
162 | pc110pad_name, pc110pad_io, pc110pad_irq); | 157 | pc110pad_name, pc110pad_io, pc110pad_irq); |
163 | 158 | ||
164 | return 0; | 159 | return 0; |
165 | } | 160 | } |
166 | 161 | ||
167 | static void __exit pc110pad_exit(void) | 162 | static void __exit pc110pad_exit(void) |
168 | { | 163 | { |
169 | input_unregister_device(&pc110pad_dev); | 164 | input_unregister_device(&pc110pad_dev); |
170 | 165 | ||
171 | outb(PC110PAD_OFF, pc110pad_io + 2); | 166 | outb(PC110PAD_OFF, pc110pad_io + 2); |
172 | 167 | ||
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 019034b21a0b..19785a6c5abd 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "synaptics.h" | 24 | #include "synaptics.h" |
25 | #include "logips2pp.h" | 25 | #include "logips2pp.h" |
26 | #include "alps.h" | 26 | #include "alps.h" |
27 | #include "lifebook.h" | ||
27 | 28 | ||
28 | #define DRIVER_DESC "PS/2 mouse driver" | 29 | #define DRIVER_DESC "PS/2 mouse driver" |
29 | 30 | ||
@@ -31,10 +32,9 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | |||
31 | MODULE_DESCRIPTION(DRIVER_DESC); | 32 | MODULE_DESCRIPTION(DRIVER_DESC); |
32 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
33 | 34 | ||
34 | static unsigned int psmouse_max_proto = -1U; | 35 | static unsigned int psmouse_max_proto = PSMOUSE_AUTO; |
35 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp); | 36 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp); |
36 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp); | 37 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp); |
37 | static char *psmouse_proto_abbrev[] = { NULL, "bare", NULL, NULL, NULL, "imps", "exps", NULL, NULL, NULL }; | ||
38 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) | 38 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) |
39 | #define param_set_proto_abbrev psmouse_set_maxproto | 39 | #define param_set_proto_abbrev psmouse_set_maxproto |
40 | #define param_get_proto_abbrev psmouse_get_maxproto | 40 | #define param_get_proto_abbrev psmouse_get_maxproto |
@@ -57,6 +57,7 @@ static unsigned int psmouse_resetafter; | |||
57 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); | 57 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); |
58 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); | 58 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); |
59 | 59 | ||
60 | PSMOUSE_DEFINE_ATTR(protocol); | ||
60 | PSMOUSE_DEFINE_ATTR(rate); | 61 | PSMOUSE_DEFINE_ATTR(rate); |
61 | PSMOUSE_DEFINE_ATTR(resolution); | 62 | PSMOUSE_DEFINE_ATTR(resolution); |
62 | PSMOUSE_DEFINE_ATTR(resetafter); | 63 | PSMOUSE_DEFINE_ATTR(resetafter); |
@@ -67,7 +68,23 @@ __obsolete_setup("psmouse_smartscroll="); | |||
67 | __obsolete_setup("psmouse_resetafter="); | 68 | __obsolete_setup("psmouse_resetafter="); |
68 | __obsolete_setup("psmouse_rate="); | 69 | __obsolete_setup("psmouse_rate="); |
69 | 70 | ||
70 | static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" }; | 71 | /* |
72 | * psmouse_sem protects all operations changing state of mouse | ||
73 | * (connecting, disconnecting, changing rate or resolution via | ||
74 | * sysfs). We could use a per-device semaphore but since there | ||
75 | * rarely more than one PS/2 mouse connected and since semaphore | ||
76 | * is taken in "slow" paths it is not worth it. | ||
77 | */ | ||
78 | static DECLARE_MUTEX(psmouse_sem); | ||
79 | |||
80 | struct psmouse_protocol { | ||
81 | enum psmouse_type type; | ||
82 | char *name; | ||
83 | char *alias; | ||
84 | int maxproto; | ||
85 | int (*detect)(struct psmouse *, int); | ||
86 | int (*init)(struct psmouse *); | ||
87 | }; | ||
71 | 88 | ||
72 | /* | 89 | /* |
73 | * psmouse_process_byte() analyzes the PS/2 data stream and reports | 90 | * psmouse_process_byte() analyzes the PS/2 data stream and reports |
@@ -407,12 +424,15 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties) | |||
407 | */ | 424 | */ |
408 | static int ps2bare_detect(struct psmouse *psmouse, int set_properties) | 425 | static int ps2bare_detect(struct psmouse *psmouse, int set_properties) |
409 | { | 426 | { |
410 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 427 | if (set_properties) { |
411 | if (!psmouse->name) psmouse->name = "Mouse"; | 428 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
429 | if (!psmouse->name) psmouse->name = "Mouse"; | ||
430 | } | ||
412 | 431 | ||
413 | return 0; | 432 | return 0; |
414 | } | 433 | } |
415 | 434 | ||
435 | |||
416 | /* | 436 | /* |
417 | * psmouse_extensions() probes for any extensions to the basic PS/2 protocol | 437 | * psmouse_extensions() probes for any extensions to the basic PS/2 protocol |
418 | * the mouse may have. | 438 | * the mouse may have. |
@@ -424,6 +444,17 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
424 | int synaptics_hardware = 0; | 444 | int synaptics_hardware = 0; |
425 | 445 | ||
426 | /* | 446 | /* |
447 | * We always check for lifebook because it does not disturb mouse | ||
448 | * (it only checks DMI information). | ||
449 | */ | ||
450 | if (lifebook_detect(psmouse, set_properties) == 0) { | ||
451 | if (max_proto > PSMOUSE_IMEX) { | ||
452 | if (!set_properties || lifebook_init(psmouse) == 0) | ||
453 | return PSMOUSE_LIFEBOOK; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | /* | ||
427 | * Try Kensington ThinkingMouse (we try first, because synaptics probe | 458 | * Try Kensington ThinkingMouse (we try first, because synaptics probe |
428 | * upsets the thinkingmouse). | 459 | * upsets the thinkingmouse). |
429 | */ | 460 | */ |
@@ -506,6 +537,103 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
506 | return PSMOUSE_PS2; | 537 | return PSMOUSE_PS2; |
507 | } | 538 | } |
508 | 539 | ||
540 | static struct psmouse_protocol psmouse_protocols[] = { | ||
541 | { | ||
542 | .type = PSMOUSE_PS2, | ||
543 | .name = "PS/2", | ||
544 | .alias = "bare", | ||
545 | .maxproto = 1, | ||
546 | .detect = ps2bare_detect, | ||
547 | }, | ||
548 | { | ||
549 | .type = PSMOUSE_PS2PP, | ||
550 | .name = "PS2++", | ||
551 | .alias = "logitech", | ||
552 | .detect = ps2pp_init, | ||
553 | }, | ||
554 | { | ||
555 | .type = PSMOUSE_THINKPS, | ||
556 | .name = "ThinkPS/2", | ||
557 | .alias = "thinkps", | ||
558 | .detect = thinking_detect, | ||
559 | }, | ||
560 | { | ||
561 | .type = PSMOUSE_GENPS, | ||
562 | .name = "GenPS/2", | ||
563 | .alias = "genius", | ||
564 | .detect = genius_detect, | ||
565 | }, | ||
566 | { | ||
567 | .type = PSMOUSE_IMPS, | ||
568 | .name = "ImPS/2", | ||
569 | .alias = "imps", | ||
570 | .maxproto = 1, | ||
571 | .detect = intellimouse_detect, | ||
572 | }, | ||
573 | { | ||
574 | .type = PSMOUSE_IMEX, | ||
575 | .name = "ImExPS/2", | ||
576 | .alias = "exps", | ||
577 | .maxproto = 1, | ||
578 | .detect = im_explorer_detect, | ||
579 | }, | ||
580 | { | ||
581 | .type = PSMOUSE_SYNAPTICS, | ||
582 | .name = "SynPS/2", | ||
583 | .alias = "synaptics", | ||
584 | .detect = synaptics_detect, | ||
585 | .init = synaptics_init, | ||
586 | }, | ||
587 | { | ||
588 | .type = PSMOUSE_ALPS, | ||
589 | .name = "AlpsPS/2", | ||
590 | .alias = "alps", | ||
591 | .detect = alps_detect, | ||
592 | .init = alps_init, | ||
593 | }, | ||
594 | { | ||
595 | .type = PSMOUSE_LIFEBOOK, | ||
596 | .name = "LBPS/2", | ||
597 | .alias = "lifebook", | ||
598 | .init = lifebook_init, | ||
599 | }, | ||
600 | { | ||
601 | .type = PSMOUSE_AUTO, | ||
602 | .name = "auto", | ||
603 | .alias = "any", | ||
604 | .maxproto = 1, | ||
605 | }, | ||
606 | }; | ||
607 | |||
608 | static struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type) | ||
609 | { | ||
610 | int i; | ||
611 | |||
612 | for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) | ||
613 | if (psmouse_protocols[i].type == type) | ||
614 | return &psmouse_protocols[i]; | ||
615 | |||
616 | WARN_ON(1); | ||
617 | return &psmouse_protocols[0]; | ||
618 | } | ||
619 | |||
620 | static struct psmouse_protocol *psmouse_protocol_by_name(const char *name, size_t len) | ||
621 | { | ||
622 | struct psmouse_protocol *p; | ||
623 | int i; | ||
624 | |||
625 | for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) { | ||
626 | p = &psmouse_protocols[i]; | ||
627 | |||
628 | if ((strlen(p->name) == len && !strncmp(p->name, name, len)) || | ||
629 | (strlen(p->alias) == len && !strncmp(p->alias, name, len))) | ||
630 | return &psmouse_protocols[i]; | ||
631 | } | ||
632 | |||
633 | return NULL; | ||
634 | } | ||
635 | |||
636 | |||
509 | /* | 637 | /* |
510 | * psmouse_probe() probes for a PS/2 mouse. | 638 | * psmouse_probe() probes for a PS/2 mouse. |
511 | */ | 639 | */ |
@@ -653,30 +781,84 @@ static void psmouse_cleanup(struct serio *serio) | |||
653 | 781 | ||
654 | static void psmouse_disconnect(struct serio *serio) | 782 | static void psmouse_disconnect(struct serio *serio) |
655 | { | 783 | { |
656 | struct psmouse *psmouse, *parent; | 784 | struct psmouse *psmouse, *parent = NULL; |
657 | 785 | ||
786 | psmouse = serio_get_drvdata(serio); | ||
787 | |||
788 | device_remove_file(&serio->dev, &psmouse_attr_protocol); | ||
658 | device_remove_file(&serio->dev, &psmouse_attr_rate); | 789 | device_remove_file(&serio->dev, &psmouse_attr_rate); |
659 | device_remove_file(&serio->dev, &psmouse_attr_resolution); | 790 | device_remove_file(&serio->dev, &psmouse_attr_resolution); |
660 | device_remove_file(&serio->dev, &psmouse_attr_resetafter); | 791 | device_remove_file(&serio->dev, &psmouse_attr_resetafter); |
661 | 792 | ||
662 | psmouse = serio_get_drvdata(serio); | 793 | down(&psmouse_sem); |
794 | |||
663 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 795 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
664 | 796 | ||
665 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 797 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
666 | parent = serio_get_drvdata(serio->parent); | 798 | parent = serio_get_drvdata(serio->parent); |
667 | if (parent->pt_deactivate) | 799 | psmouse_deactivate(parent); |
668 | parent->pt_deactivate(parent); | ||
669 | } | 800 | } |
670 | 801 | ||
671 | if (psmouse->disconnect) | 802 | if (psmouse->disconnect) |
672 | psmouse->disconnect(psmouse); | 803 | psmouse->disconnect(psmouse); |
673 | 804 | ||
805 | if (parent && parent->pt_deactivate) | ||
806 | parent->pt_deactivate(parent); | ||
807 | |||
674 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 808 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
675 | 809 | ||
676 | input_unregister_device(&psmouse->dev); | 810 | input_unregister_device(&psmouse->dev); |
677 | serio_close(serio); | 811 | serio_close(serio); |
678 | serio_set_drvdata(serio, NULL); | 812 | serio_set_drvdata(serio, NULL); |
679 | kfree(psmouse); | 813 | kfree(psmouse); |
814 | |||
815 | if (parent) | ||
816 | psmouse_activate(parent); | ||
817 | |||
818 | up(&psmouse_sem); | ||
819 | } | ||
820 | |||
821 | static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto) | ||
822 | { | ||
823 | memset(&psmouse->dev, 0, sizeof(struct input_dev)); | ||
824 | |||
825 | init_input_dev(&psmouse->dev); | ||
826 | |||
827 | psmouse->dev.private = psmouse; | ||
828 | psmouse->dev.dev = &psmouse->ps2dev.serio->dev; | ||
829 | |||
830 | psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
831 | psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
832 | psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
833 | |||
834 | psmouse->set_rate = psmouse_set_rate; | ||
835 | psmouse->set_resolution = psmouse_set_resolution; | ||
836 | psmouse->protocol_handler = psmouse_process_byte; | ||
837 | psmouse->pktsize = 3; | ||
838 | |||
839 | if (proto && (proto->detect || proto->init)) { | ||
840 | if (proto->detect && proto->detect(psmouse, 1) < 0) | ||
841 | return -1; | ||
842 | |||
843 | if (proto->init && proto->init(psmouse) < 0) | ||
844 | return -1; | ||
845 | |||
846 | psmouse->type = proto->type; | ||
847 | } | ||
848 | else | ||
849 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | ||
850 | |||
851 | sprintf(psmouse->devname, "%s %s %s", | ||
852 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); | ||
853 | |||
854 | psmouse->dev.name = psmouse->devname; | ||
855 | psmouse->dev.phys = psmouse->phys; | ||
856 | psmouse->dev.id.bustype = BUS_I8042; | ||
857 | psmouse->dev.id.vendor = 0x0002; | ||
858 | psmouse->dev.id.product = psmouse->type; | ||
859 | psmouse->dev.id.version = psmouse->model; | ||
860 | |||
861 | return 0; | ||
680 | } | 862 | } |
681 | 863 | ||
682 | /* | 864 | /* |
@@ -688,6 +870,8 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
688 | struct psmouse *psmouse, *parent = NULL; | 870 | struct psmouse *psmouse, *parent = NULL; |
689 | int retval; | 871 | int retval; |
690 | 872 | ||
873 | down(&psmouse_sem); | ||
874 | |||
691 | /* | 875 | /* |
692 | * If this is a pass-through port deactivate parent so the device | 876 | * If this is a pass-through port deactivate parent so the device |
693 | * connected to this port can be successfully identified | 877 | * connected to this port can be successfully identified |
@@ -697,20 +881,14 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
697 | psmouse_deactivate(parent); | 881 | psmouse_deactivate(parent); |
698 | } | 882 | } |
699 | 883 | ||
700 | if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) { | 884 | if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) { |
701 | retval = -ENOMEM; | 885 | retval = -ENOMEM; |
702 | goto out; | 886 | goto out; |
703 | } | 887 | } |
704 | 888 | ||
705 | memset(psmouse, 0, sizeof(struct psmouse)); | ||
706 | |||
707 | ps2_init(&psmouse->ps2dev, serio); | 889 | ps2_init(&psmouse->ps2dev, serio); |
708 | sprintf(psmouse->phys, "%s/input0", serio->phys); | 890 | sprintf(psmouse->phys, "%s/input0", serio->phys); |
709 | psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 891 | |
710 | psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
711 | psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
712 | psmouse->dev.private = psmouse; | ||
713 | psmouse->dev.dev = &serio->dev; | ||
714 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | 892 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); |
715 | 893 | ||
716 | serio_set_drvdata(serio, psmouse); | 894 | serio_set_drvdata(serio, psmouse); |
@@ -734,25 +912,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
734 | psmouse->resolution = psmouse_resolution; | 912 | psmouse->resolution = psmouse_resolution; |
735 | psmouse->resetafter = psmouse_resetafter; | 913 | psmouse->resetafter = psmouse_resetafter; |
736 | psmouse->smartscroll = psmouse_smartscroll; | 914 | psmouse->smartscroll = psmouse_smartscroll; |
737 | psmouse->set_rate = psmouse_set_rate; | ||
738 | psmouse->set_resolution = psmouse_set_resolution; | ||
739 | psmouse->protocol_handler = psmouse_process_byte; | ||
740 | psmouse->pktsize = 3; | ||
741 | 915 | ||
742 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | 916 | psmouse_switch_protocol(psmouse, NULL); |
743 | |||
744 | sprintf(psmouse->devname, "%s %s %s", | ||
745 | psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name); | ||
746 | |||
747 | psmouse->dev.name = psmouse->devname; | ||
748 | psmouse->dev.phys = psmouse->phys; | ||
749 | psmouse->dev.id.bustype = BUS_I8042; | ||
750 | psmouse->dev.id.vendor = 0x0002; | ||
751 | psmouse->dev.id.product = psmouse->type; | ||
752 | psmouse->dev.id.version = psmouse->model; | ||
753 | 917 | ||
754 | input_register_device(&psmouse->dev); | 918 | input_register_device(&psmouse->dev); |
755 | |||
756 | printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); | 919 | printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); |
757 | 920 | ||
758 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 921 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
@@ -762,6 +925,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
762 | if (parent && parent->pt_activate) | 925 | if (parent && parent->pt_activate) |
763 | parent->pt_activate(parent); | 926 | parent->pt_activate(parent); |
764 | 927 | ||
928 | device_create_file(&serio->dev, &psmouse_attr_protocol); | ||
765 | device_create_file(&serio->dev, &psmouse_attr_rate); | 929 | device_create_file(&serio->dev, &psmouse_attr_rate); |
766 | device_create_file(&serio->dev, &psmouse_attr_resolution); | 930 | device_create_file(&serio->dev, &psmouse_attr_resolution); |
767 | device_create_file(&serio->dev, &psmouse_attr_resetafter); | 931 | device_create_file(&serio->dev, &psmouse_attr_resetafter); |
@@ -771,10 +935,11 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
771 | retval = 0; | 935 | retval = 0; |
772 | 936 | ||
773 | out: | 937 | out: |
774 | /* If this is a pass-through port the parent awaits to be activated */ | 938 | /* If this is a pass-through port the parent needs to be re-activated */ |
775 | if (parent) | 939 | if (parent) |
776 | psmouse_activate(parent); | 940 | psmouse_activate(parent); |
777 | 941 | ||
942 | up(&psmouse_sem); | ||
778 | return retval; | 943 | return retval; |
779 | } | 944 | } |
780 | 945 | ||
@@ -791,6 +956,8 @@ static int psmouse_reconnect(struct serio *serio) | |||
791 | return -1; | 956 | return -1; |
792 | } | 957 | } |
793 | 958 | ||
959 | down(&psmouse_sem); | ||
960 | |||
794 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 961 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
795 | parent = serio_get_drvdata(serio->parent); | 962 | parent = serio_get_drvdata(serio->parent); |
796 | psmouse_deactivate(parent); | 963 | psmouse_deactivate(parent); |
@@ -823,6 +990,7 @@ out: | |||
823 | if (parent) | 990 | if (parent) |
824 | psmouse_activate(parent); | 991 | psmouse_activate(parent); |
825 | 992 | ||
993 | up(&psmouse_sem); | ||
826 | return rc; | 994 | return rc; |
827 | } | 995 | } |
828 | 996 | ||
@@ -893,26 +1061,109 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun | |||
893 | 1061 | ||
894 | if (serio->drv != &psmouse_drv) { | 1062 | if (serio->drv != &psmouse_drv) { |
895 | retval = -ENODEV; | 1063 | retval = -ENODEV; |
896 | goto out; | 1064 | goto out_unpin; |
1065 | } | ||
1066 | |||
1067 | retval = down_interruptible(&psmouse_sem); | ||
1068 | if (retval) | ||
1069 | goto out_unpin; | ||
1070 | |||
1071 | if (psmouse->state == PSMOUSE_IGNORE) { | ||
1072 | retval = -ENODEV; | ||
1073 | goto out_up; | ||
897 | } | 1074 | } |
898 | 1075 | ||
899 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 1076 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
900 | parent = serio_get_drvdata(serio->parent); | 1077 | parent = serio_get_drvdata(serio->parent); |
901 | psmouse_deactivate(parent); | 1078 | psmouse_deactivate(parent); |
902 | } | 1079 | } |
1080 | |||
903 | psmouse_deactivate(psmouse); | 1081 | psmouse_deactivate(psmouse); |
904 | 1082 | ||
905 | retval = handler(psmouse, buf, count); | 1083 | retval = handler(psmouse, buf, count); |
906 | 1084 | ||
907 | psmouse_activate(psmouse); | 1085 | if (retval != -ENODEV) |
1086 | psmouse_activate(psmouse); | ||
1087 | |||
908 | if (parent) | 1088 | if (parent) |
909 | psmouse_activate(parent); | 1089 | psmouse_activate(parent); |
910 | 1090 | ||
911 | out: | 1091 | out_up: |
1092 | up(&psmouse_sem); | ||
1093 | out_unpin: | ||
912 | serio_unpin_driver(serio); | 1094 | serio_unpin_driver(serio); |
913 | return retval; | 1095 | return retval; |
914 | } | 1096 | } |
915 | 1097 | ||
1098 | static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf) | ||
1099 | { | ||
1100 | return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name); | ||
1101 | } | ||
1102 | |||
1103 | static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count) | ||
1104 | { | ||
1105 | struct serio *serio = psmouse->ps2dev.serio; | ||
1106 | struct psmouse *parent = NULL; | ||
1107 | struct psmouse_protocol *proto; | ||
1108 | int retry = 0; | ||
1109 | |||
1110 | if (!(proto = psmouse_protocol_by_name(buf, count))) | ||
1111 | return -EINVAL; | ||
1112 | |||
1113 | if (psmouse->type == proto->type) | ||
1114 | return count; | ||
1115 | |||
1116 | while (serio->child) { | ||
1117 | if (++retry > 3) { | ||
1118 | printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n"); | ||
1119 | return -EIO; | ||
1120 | } | ||
1121 | |||
1122 | up(&psmouse_sem); | ||
1123 | serio_unpin_driver(serio); | ||
1124 | serio_unregister_child_port(serio); | ||
1125 | serio_pin_driver_uninterruptible(serio); | ||
1126 | down(&psmouse_sem); | ||
1127 | |||
1128 | if (serio->drv != &psmouse_drv) | ||
1129 | return -ENODEV; | ||
1130 | |||
1131 | if (psmouse->type == proto->type) | ||
1132 | return count; /* switched by other thread */ | ||
1133 | } | ||
1134 | |||
1135 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | ||
1136 | parent = serio_get_drvdata(serio->parent); | ||
1137 | if (parent->pt_deactivate) | ||
1138 | parent->pt_deactivate(parent); | ||
1139 | } | ||
1140 | |||
1141 | if (psmouse->disconnect) | ||
1142 | psmouse->disconnect(psmouse); | ||
1143 | |||
1144 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
1145 | input_unregister_device(&psmouse->dev); | ||
1146 | |||
1147 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | ||
1148 | |||
1149 | if (psmouse_switch_protocol(psmouse, proto) < 0) { | ||
1150 | psmouse_reset(psmouse); | ||
1151 | /* default to PSMOUSE_PS2 */ | ||
1152 | psmouse_switch_protocol(psmouse, &psmouse_protocols[0]); | ||
1153 | } | ||
1154 | |||
1155 | psmouse_initialize(psmouse); | ||
1156 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
1157 | |||
1158 | input_register_device(&psmouse->dev); | ||
1159 | printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); | ||
1160 | |||
1161 | if (parent && parent->pt_activate) | ||
1162 | parent->pt_activate(parent); | ||
1163 | |||
1164 | return count; | ||
1165 | } | ||
1166 | |||
916 | static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf) | 1167 | static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf) |
917 | { | 1168 | { |
918 | return sprintf(buf, "%d\n", psmouse->rate); | 1169 | return sprintf(buf, "%d\n", psmouse->rate); |
@@ -969,34 +1220,26 @@ static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char * | |||
969 | 1220 | ||
970 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) | 1221 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) |
971 | { | 1222 | { |
972 | int i; | 1223 | struct psmouse_protocol *proto; |
973 | 1224 | ||
974 | if (!val) | 1225 | if (!val) |
975 | return -EINVAL; | 1226 | return -EINVAL; |
976 | 1227 | ||
977 | if (!strncmp(val, "any", 3)) { | 1228 | proto = psmouse_protocol_by_name(val, strlen(val)); |
978 | *((unsigned int *)kp->arg) = -1U; | ||
979 | return 0; | ||
980 | } | ||
981 | 1229 | ||
982 | for (i = 0; i < ARRAY_SIZE(psmouse_proto_abbrev); i++) { | 1230 | if (!proto || !proto->maxproto) |
983 | if (!psmouse_proto_abbrev[i]) | 1231 | return -EINVAL; |
984 | continue; | ||
985 | 1232 | ||
986 | if (!strncmp(val, psmouse_proto_abbrev[i], strlen(psmouse_proto_abbrev[i]))) { | 1233 | *((unsigned int *)kp->arg) = proto->type; |
987 | *((unsigned int *)kp->arg) = i; | ||
988 | return 0; | ||
989 | } | ||
990 | } | ||
991 | 1234 | ||
992 | return -EINVAL; \ | 1235 | return 0; \ |
993 | } | 1236 | } |
994 | 1237 | ||
995 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) | 1238 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) |
996 | { | 1239 | { |
997 | return sprintf(buffer, "%s\n", | 1240 | int type = *((unsigned int *)kp->arg); |
998 | psmouse_max_proto < ARRAY_SIZE(psmouse_proto_abbrev) ? | 1241 | |
999 | psmouse_proto_abbrev[psmouse_max_proto] : "any"); | 1242 | return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name); |
1000 | } | 1243 | } |
1001 | 1244 | ||
1002 | static int __init psmouse_init(void) | 1245 | static int __init psmouse_init(void) |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 79e17a0c4664..86691cf43433 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -77,6 +77,8 @@ enum psmouse_type { | |||
77 | PSMOUSE_IMEX, | 77 | PSMOUSE_IMEX, |
78 | PSMOUSE_SYNAPTICS, | 78 | PSMOUSE_SYNAPTICS, |
79 | PSMOUSE_ALPS, | 79 | PSMOUSE_ALPS, |
80 | PSMOUSE_LIFEBOOK, | ||
81 | PSMOUSE_AUTO /* This one should always be last */ | ||
80 | }; | 82 | }; |
81 | 83 | ||
82 | int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); | 84 | int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); |
@@ -99,7 +101,7 @@ static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute | |||
99 | { \ | 101 | { \ |
100 | return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \ | 102 | return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \ |
101 | } \ | 103 | } \ |
102 | static struct device_attribute psmouse_attr_##_name = \ | 104 | static struct device_attribute psmouse_attr_##_name = \ |
103 | __ATTR(_name, S_IWUSR | S_IRUGO, \ | 105 | __ATTR(_name, S_IWUSR | S_IRUGO, \ |
104 | psmouse_do_show_##_name, psmouse_do_set_##_name); | 106 | psmouse_do_show_##_name, psmouse_do_set_##_name); |
105 | 107 | ||
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c index 7280f68afcee..8fe1212b8fd7 100644 --- a/drivers/input/mouse/rpcmouse.c +++ b/drivers/input/mouse/rpcmouse.c | |||
@@ -59,7 +59,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
59 | b = (short) (__raw_readl(0xe0310000) ^ 0x70); | 59 | b = (short) (__raw_readl(0xe0310000) ^ 0x70); |
60 | 60 | ||
61 | dx = x - rpcmouse_lastx; | 61 | dx = x - rpcmouse_lastx; |
62 | dy = y - rpcmouse_lasty; | 62 | dy = y - rpcmouse_lasty; |
63 | 63 | ||
64 | rpcmouse_lastx = x; | 64 | rpcmouse_lastx = x; |
65 | rpcmouse_lasty = y; | 65 | rpcmouse_lasty = y; |
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index b2cb101c8110..f024be9b44d2 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers) | 2 | * Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers) |
3 | * DEC VSXXX-GA mouse (rectangular mouse, with ball) | 3 | * DEC VSXXX-GA mouse (rectangular mouse, with ball) |
4 | * DEC VSXXX-AB tablet (digitizer with hair cross or stylus) | 4 | * DEC VSXXX-AB tablet (digitizer with hair cross or stylus) |
5 | * | 5 | * |
6 | * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de> | 6 | * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de> |
7 | * | 7 | * |
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 062848ac7e6b..c6194a9dd174 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
@@ -220,6 +220,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h | |||
220 | struct mousedev_list *list; | 220 | struct mousedev_list *list; |
221 | struct mousedev_motion *p; | 221 | struct mousedev_motion *p; |
222 | unsigned long flags; | 222 | unsigned long flags; |
223 | int wake_readers = 0; | ||
223 | 224 | ||
224 | list_for_each_entry(list, &mousedev->list, node) { | 225 | list_for_each_entry(list, &mousedev->list, node) { |
225 | spin_lock_irqsave(&list->packet_lock, flags); | 226 | spin_lock_irqsave(&list->packet_lock, flags); |
@@ -255,11 +256,14 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h | |||
255 | 256 | ||
256 | spin_unlock_irqrestore(&list->packet_lock, flags); | 257 | spin_unlock_irqrestore(&list->packet_lock, flags); |
257 | 258 | ||
258 | if (list->ready) | 259 | if (list->ready) { |
259 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | 260 | kill_fasync(&list->fasync, SIGIO, POLL_IN); |
261 | wake_readers = 1; | ||
262 | } | ||
260 | } | 263 | } |
261 | 264 | ||
262 | wake_up_interruptible(&mousedev->wait); | 265 | if (wake_readers) |
266 | wake_up_interruptible(&mousedev->wait); | ||
263 | } | 267 | } |
264 | 268 | ||
265 | static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) | 269 | static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index c978657068c5..d4c990f7c85e 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
@@ -29,6 +29,7 @@ MODULE_LICENSE("GPL"); | |||
29 | 29 | ||
30 | EXPORT_SYMBOL(ps2_init); | 30 | EXPORT_SYMBOL(ps2_init); |
31 | EXPORT_SYMBOL(ps2_sendbyte); | 31 | EXPORT_SYMBOL(ps2_sendbyte); |
32 | EXPORT_SYMBOL(ps2_drain); | ||
32 | EXPORT_SYMBOL(ps2_command); | 33 | EXPORT_SYMBOL(ps2_command); |
33 | EXPORT_SYMBOL(ps2_schedule_command); | 34 | EXPORT_SYMBOL(ps2_schedule_command); |
34 | EXPORT_SYMBOL(ps2_handle_ack); | 35 | EXPORT_SYMBOL(ps2_handle_ack); |
@@ -45,11 +46,11 @@ struct ps2work { | |||
45 | 46 | ||
46 | 47 | ||
47 | /* | 48 | /* |
48 | * ps2_sendbyte() sends a byte to the mouse, and waits for acknowledge. | 49 | * ps2_sendbyte() sends a byte to the device and waits for acknowledge. |
49 | * It doesn't handle retransmission, though it could - because when there would | 50 | * It doesn't handle retransmission, though it could - because if there |
50 | * be need for retransmissions, the mouse has to be replaced anyway. | 51 | * is a need for retransmissions device has to be replaced anyway. |
51 | * | 52 | * |
52 | * ps2_sendbyte() can only be called from a process context | 53 | * ps2_sendbyte() can only be called from a process context. |
53 | */ | 54 | */ |
54 | 55 | ||
55 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) | 56 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) |
@@ -72,6 +73,91 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) | |||
72 | } | 73 | } |
73 | 74 | ||
74 | /* | 75 | /* |
76 | * ps2_drain() waits for device to transmit requested number of bytes | ||
77 | * and discards them. | ||
78 | */ | ||
79 | |||
80 | void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) | ||
81 | { | ||
82 | if (maxbytes > sizeof(ps2dev->cmdbuf)) { | ||
83 | WARN_ON(1); | ||
84 | maxbytes = sizeof(ps2dev->cmdbuf); | ||
85 | } | ||
86 | |||
87 | down(&ps2dev->cmd_sem); | ||
88 | |||
89 | serio_pause_rx(ps2dev->serio); | ||
90 | ps2dev->flags = PS2_FLAG_CMD; | ||
91 | ps2dev->cmdcnt = maxbytes; | ||
92 | serio_continue_rx(ps2dev->serio); | ||
93 | |||
94 | wait_event_timeout(ps2dev->wait, | ||
95 | !(ps2dev->flags & PS2_FLAG_CMD), | ||
96 | msecs_to_jiffies(timeout)); | ||
97 | up(&ps2dev->cmd_sem); | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * ps2_is_keyboard_id() checks received ID byte against the list of | ||
102 | * known keyboard IDs. | ||
103 | */ | ||
104 | |||
105 | static inline int ps2_is_keyboard_id(char id_byte) | ||
106 | { | ||
107 | static char keyboard_ids[] = { | ||
108 | 0xab, /* Regular keyboards */ | ||
109 | 0xac, /* NCD Sun keyboard */ | ||
110 | 0x2b, /* Trust keyboard, translated */ | ||
111 | 0x5d, /* Trust keyboard */ | ||
112 | 0x60, /* NMB SGI keyboard, translated */ | ||
113 | 0x47, /* NMB SGI keyboard */ | ||
114 | }; | ||
115 | |||
116 | return memchr(keyboard_ids, id_byte, sizeof(keyboard_ids)) != NULL; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * ps2_adjust_timeout() is called after receiving 1st byte of command | ||
121 | * response and tries to reduce remaining timeout to speed up command | ||
122 | * completion. | ||
123 | */ | ||
124 | |||
125 | static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout) | ||
126 | { | ||
127 | switch (command) { | ||
128 | case PS2_CMD_RESET_BAT: | ||
129 | /* | ||
130 | * Device has sent the first response byte after | ||
131 | * reset command, reset is thus done, so we can | ||
132 | * shorten the timeout. | ||
133 | * The next byte will come soon (keyboard) or not | ||
134 | * at all (mouse). | ||
135 | */ | ||
136 | if (timeout > msecs_to_jiffies(100)) | ||
137 | timeout = msecs_to_jiffies(100); | ||
138 | break; | ||
139 | |||
140 | case PS2_CMD_GETID: | ||
141 | /* | ||
142 | * If device behind the port is not a keyboard there | ||
143 | * won't be 2nd byte of ID response. | ||
144 | */ | ||
145 | if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) { | ||
146 | serio_pause_rx(ps2dev->serio); | ||
147 | ps2dev->flags = ps2dev->cmdcnt = 0; | ||
148 | serio_continue_rx(ps2dev->serio); | ||
149 | timeout = 0; | ||
150 | } | ||
151 | break; | ||
152 | |||
153 | default: | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | return timeout; | ||
158 | } | ||
159 | |||
160 | /* | ||
75 | * ps2_command() sends a command and its parameters to the mouse, | 161 | * ps2_command() sends a command and its parameters to the mouse, |
76 | * then waits for the response and puts it in the param array. | 162 | * then waits for the response and puts it in the param array. |
77 | * | 163 | * |
@@ -86,6 +172,11 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
86 | int rc = -1; | 172 | int rc = -1; |
87 | int i; | 173 | int i; |
88 | 174 | ||
175 | if (receive > sizeof(ps2dev->cmdbuf)) { | ||
176 | WARN_ON(1); | ||
177 | return -1; | ||
178 | } | ||
179 | |||
89 | down(&ps2dev->cmd_sem); | 180 | down(&ps2dev->cmd_sem); |
90 | 181 | ||
91 | serio_pause_rx(ps2dev->serio); | 182 | serio_pause_rx(ps2dev->serio); |
@@ -101,10 +192,9 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
101 | * ACKing the reset command, and so it can take a long | 192 | * ACKing the reset command, and so it can take a long |
102 | * time before the ACK arrrives. | 193 | * time before the ACK arrrives. |
103 | */ | 194 | */ |
104 | if (command & 0xff) | 195 | if (ps2_sendbyte(ps2dev, command & 0xff, |
105 | if (ps2_sendbyte(ps2dev, command & 0xff, | 196 | command == PS2_CMD_RESET_BAT ? 1000 : 200)) |
106 | command == PS2_CMD_RESET_BAT ? 1000 : 200)) | 197 | goto out; |
107 | goto out; | ||
108 | 198 | ||
109 | for (i = 0; i < send; i++) | 199 | for (i = 0; i < send; i++) |
110 | if (ps2_sendbyte(ps2dev, param[i], 200)) | 200 | if (ps2_sendbyte(ps2dev, param[i], 200)) |
@@ -120,33 +210,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
120 | 210 | ||
121 | if (ps2dev->cmdcnt && timeout > 0) { | 211 | if (ps2dev->cmdcnt && timeout > 0) { |
122 | 212 | ||
123 | if (command == PS2_CMD_RESET_BAT && timeout > msecs_to_jiffies(100)) { | 213 | timeout = ps2_adjust_timeout(ps2dev, command, timeout); |
124 | /* | ||
125 | * Device has sent the first response byte | ||
126 | * after a reset command, reset is thus done, | ||
127 | * shorten the timeout. The next byte will come | ||
128 | * soon (keyboard) or not at all (mouse). | ||
129 | */ | ||
130 | timeout = msecs_to_jiffies(100); | ||
131 | } | ||
132 | |||
133 | if (command == PS2_CMD_GETID && | ||
134 | ps2dev->cmdbuf[receive - 1] != 0xab && /* Regular keyboards */ | ||
135 | ps2dev->cmdbuf[receive - 1] != 0xac && /* NCD Sun keyboard */ | ||
136 | ps2dev->cmdbuf[receive - 1] != 0x2b && /* Trust keyboard, translated */ | ||
137 | ps2dev->cmdbuf[receive - 1] != 0x5d && /* Trust keyboard */ | ||
138 | ps2dev->cmdbuf[receive - 1] != 0x60 && /* NMB SGI keyboard, translated */ | ||
139 | ps2dev->cmdbuf[receive - 1] != 0x47) { /* NMB SGI keyboard */ | ||
140 | /* | ||
141 | * Device behind the port is not a keyboard | ||
142 | * so we don't need to wait for the 2nd byte | ||
143 | * of ID response. | ||
144 | */ | ||
145 | serio_pause_rx(ps2dev->serio); | ||
146 | ps2dev->flags = ps2dev->cmdcnt = 0; | ||
147 | serio_continue_rx(ps2dev->serio); | ||
148 | } | ||
149 | |||
150 | wait_event_timeout(ps2dev->wait, | 214 | wait_event_timeout(ps2dev->wait, |
151 | !(ps2dev->flags & PS2_FLAG_CMD), timeout); | 215 | !(ps2dev->flags & PS2_FLAG_CMD), timeout); |
152 | } | 216 | } |
@@ -160,7 +224,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
160 | 224 | ||
161 | rc = 0; | 225 | rc = 0; |
162 | 226 | ||
163 | out: | 227 | out: |
164 | serio_pause_rx(ps2dev->serio); | 228 | serio_pause_rx(ps2dev->serio); |
165 | ps2dev->flags = 0; | 229 | ps2dev->flags = 0; |
166 | serio_continue_rx(ps2dev->serio); | 230 | serio_continue_rx(ps2dev->serio); |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 341824c48529..f367695e69b5 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -31,10 +31,9 @@ | |||
31 | #include <linux/serio.h> | 31 | #include <linux/serio.h> |
32 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
33 | #include <linux/wait.h> | 33 | #include <linux/wait.h> |
34 | #include <linux/completion.h> | ||
35 | #include <linux/sched.h> | 34 | #include <linux/sched.h> |
36 | #include <linux/smp_lock.h> | ||
37 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/kthread.h> | ||
38 | 37 | ||
39 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 38 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
40 | MODULE_DESCRIPTION("Serio abstraction core"); | 39 | MODULE_DESCRIPTION("Serio abstraction core"); |
@@ -43,6 +42,7 @@ MODULE_LICENSE("GPL"); | |||
43 | EXPORT_SYMBOL(serio_interrupt); | 42 | EXPORT_SYMBOL(serio_interrupt); |
44 | EXPORT_SYMBOL(__serio_register_port); | 43 | EXPORT_SYMBOL(__serio_register_port); |
45 | EXPORT_SYMBOL(serio_unregister_port); | 44 | EXPORT_SYMBOL(serio_unregister_port); |
45 | EXPORT_SYMBOL(serio_unregister_child_port); | ||
46 | EXPORT_SYMBOL(__serio_unregister_port_delayed); | 46 | EXPORT_SYMBOL(__serio_unregister_port_delayed); |
47 | EXPORT_SYMBOL(__serio_register_driver); | 47 | EXPORT_SYMBOL(__serio_register_driver); |
48 | EXPORT_SYMBOL(serio_unregister_driver); | 48 | EXPORT_SYMBOL(serio_unregister_driver); |
@@ -68,6 +68,37 @@ static void serio_destroy_port(struct serio *serio); | |||
68 | static void serio_reconnect_port(struct serio *serio); | 68 | static void serio_reconnect_port(struct serio *serio); |
69 | static void serio_disconnect_port(struct serio *serio); | 69 | static void serio_disconnect_port(struct serio *serio); |
70 | 70 | ||
71 | static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) | ||
72 | { | ||
73 | int retval; | ||
74 | |||
75 | down(&serio->drv_sem); | ||
76 | retval = drv->connect(serio, drv); | ||
77 | up(&serio->drv_sem); | ||
78 | |||
79 | return retval; | ||
80 | } | ||
81 | |||
82 | static int serio_reconnect_driver(struct serio *serio) | ||
83 | { | ||
84 | int retval = -1; | ||
85 | |||
86 | down(&serio->drv_sem); | ||
87 | if (serio->drv && serio->drv->reconnect) | ||
88 | retval = serio->drv->reconnect(serio); | ||
89 | up(&serio->drv_sem); | ||
90 | |||
91 | return retval; | ||
92 | } | ||
93 | |||
94 | static void serio_disconnect_driver(struct serio *serio) | ||
95 | { | ||
96 | down(&serio->drv_sem); | ||
97 | if (serio->drv) | ||
98 | serio->drv->disconnect(serio); | ||
99 | up(&serio->drv_sem); | ||
100 | } | ||
101 | |||
71 | static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) | 102 | static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) |
72 | { | 103 | { |
73 | while (ids->type || ids->proto) { | 104 | while (ids->type || ids->proto) { |
@@ -91,7 +122,7 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) | |||
91 | 122 | ||
92 | if (serio_match_port(drv->id_table, serio)) { | 123 | if (serio_match_port(drv->id_table, serio)) { |
93 | serio->dev.driver = &drv->driver; | 124 | serio->dev.driver = &drv->driver; |
94 | if (drv->connect(serio, drv)) { | 125 | if (serio_connect_driver(serio, drv)) { |
95 | serio->dev.driver = NULL; | 126 | serio->dev.driver = NULL; |
96 | goto out; | 127 | goto out; |
97 | } | 128 | } |
@@ -138,8 +169,7 @@ struct serio_event { | |||
138 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ | 169 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ |
139 | static LIST_HEAD(serio_event_list); | 170 | static LIST_HEAD(serio_event_list); |
140 | static DECLARE_WAIT_QUEUE_HEAD(serio_wait); | 171 | static DECLARE_WAIT_QUEUE_HEAD(serio_wait); |
141 | static DECLARE_COMPLETION(serio_exited); | 172 | static struct task_struct *serio_task; |
142 | static int serio_pid; | ||
143 | 173 | ||
144 | static void serio_queue_event(void *object, struct module *owner, | 174 | static void serio_queue_event(void *object, struct module *owner, |
145 | enum serio_event_type event_type) | 175 | enum serio_event_type event_type) |
@@ -150,12 +180,12 @@ static void serio_queue_event(void *object, struct module *owner, | |||
150 | spin_lock_irqsave(&serio_event_lock, flags); | 180 | spin_lock_irqsave(&serio_event_lock, flags); |
151 | 181 | ||
152 | /* | 182 | /* |
153 | * Scan event list for the other events for the same serio port, | 183 | * Scan event list for the other events for the same serio port, |
154 | * starting with the most recent one. If event is the same we | 184 | * starting with the most recent one. If event is the same we |
155 | * do not need add new one. If event is of different type we | 185 | * do not need add new one. If event is of different type we |
156 | * need to add this event and should not look further because | 186 | * need to add this event and should not look further because |
157 | * we need to preseve sequence of distinct events. | 187 | * we need to preseve sequence of distinct events. |
158 | */ | 188 | */ |
159 | list_for_each_entry_reverse(event, &serio_event_list, node) { | 189 | list_for_each_entry_reverse(event, &serio_event_list, node) { |
160 | if (event->object == object) { | 190 | if (event->object == object) { |
161 | if (event->type == event_type) | 191 | if (event->type == event_type) |
@@ -337,20 +367,15 @@ static struct serio *serio_get_pending_child(struct serio *parent) | |||
337 | 367 | ||
338 | static int serio_thread(void *nothing) | 368 | static int serio_thread(void *nothing) |
339 | { | 369 | { |
340 | lock_kernel(); | ||
341 | daemonize("kseriod"); | ||
342 | allow_signal(SIGTERM); | ||
343 | |||
344 | do { | 370 | do { |
345 | serio_handle_events(); | 371 | serio_handle_events(); |
346 | wait_event_interruptible(serio_wait, !list_empty(&serio_event_list)); | 372 | wait_event_interruptible(serio_wait, |
373 | kthread_should_stop() || !list_empty(&serio_event_list)); | ||
347 | try_to_freeze(); | 374 | try_to_freeze(); |
348 | } while (!signal_pending(current)); | 375 | } while (!kthread_should_stop()); |
349 | 376 | ||
350 | printk(KERN_DEBUG "serio: kseriod exiting\n"); | 377 | printk(KERN_DEBUG "serio: kseriod exiting\n"); |
351 | 378 | return 0; | |
352 | unlock_kernel(); | ||
353 | complete_and_exit(&serio_exited, 0); | ||
354 | } | 379 | } |
355 | 380 | ||
356 | 381 | ||
@@ -557,7 +582,7 @@ static void serio_destroy_port(struct serio *serio) | |||
557 | static void serio_reconnect_port(struct serio *serio) | 582 | static void serio_reconnect_port(struct serio *serio) |
558 | { | 583 | { |
559 | do { | 584 | do { |
560 | if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { | 585 | if (serio_reconnect_driver(serio)) { |
561 | serio_disconnect_port(serio); | 586 | serio_disconnect_port(serio); |
562 | serio_find_driver(serio); | 587 | serio_find_driver(serio); |
563 | /* Ok, old children are now gone, we are done */ | 588 | /* Ok, old children are now gone, we are done */ |
@@ -630,6 +655,19 @@ void serio_unregister_port(struct serio *serio) | |||
630 | } | 655 | } |
631 | 656 | ||
632 | /* | 657 | /* |
658 | * Safely unregisters child port if one is present. | ||
659 | */ | ||
660 | void serio_unregister_child_port(struct serio *serio) | ||
661 | { | ||
662 | down(&serio_sem); | ||
663 | if (serio->child) { | ||
664 | serio_disconnect_port(serio->child); | ||
665 | serio_destroy_port(serio->child); | ||
666 | } | ||
667 | up(&serio_sem); | ||
668 | } | ||
669 | |||
670 | /* | ||
633 | * Submits register request to kseriod for subsequent execution. | 671 | * Submits register request to kseriod for subsequent execution. |
634 | * Can be used when it is not obvious whether the serio_sem is | 672 | * Can be used when it is not obvious whether the serio_sem is |
635 | * taken or not and when delayed execution is feasible. | 673 | * taken or not and when delayed execution is feasible. |
@@ -686,15 +724,14 @@ static int serio_driver_probe(struct device *dev) | |||
686 | struct serio *serio = to_serio_port(dev); | 724 | struct serio *serio = to_serio_port(dev); |
687 | struct serio_driver *drv = to_serio_driver(dev->driver); | 725 | struct serio_driver *drv = to_serio_driver(dev->driver); |
688 | 726 | ||
689 | return drv->connect(serio, drv); | 727 | return serio_connect_driver(serio, drv); |
690 | } | 728 | } |
691 | 729 | ||
692 | static int serio_driver_remove(struct device *dev) | 730 | static int serio_driver_remove(struct device *dev) |
693 | { | 731 | { |
694 | struct serio *serio = to_serio_port(dev); | 732 | struct serio *serio = to_serio_port(dev); |
695 | struct serio_driver *drv = to_serio_driver(dev->driver); | ||
696 | 733 | ||
697 | drv->disconnect(serio); | 734 | serio_disconnect_driver(serio); |
698 | return 0; | 735 | return 0; |
699 | } | 736 | } |
700 | 737 | ||
@@ -730,11 +767,9 @@ start_over: | |||
730 | 767 | ||
731 | static void serio_set_drv(struct serio *serio, struct serio_driver *drv) | 768 | static void serio_set_drv(struct serio *serio, struct serio_driver *drv) |
732 | { | 769 | { |
733 | down(&serio->drv_sem); | ||
734 | serio_pause_rx(serio); | 770 | serio_pause_rx(serio); |
735 | serio->drv = drv; | 771 | serio->drv = drv; |
736 | serio_continue_rx(serio); | 772 | serio_continue_rx(serio); |
737 | up(&serio->drv_sem); | ||
738 | } | 773 | } |
739 | 774 | ||
740 | static int serio_bus_match(struct device *dev, struct device_driver *drv) | 775 | static int serio_bus_match(struct device *dev, struct device_driver *drv) |
@@ -794,7 +829,7 @@ static int serio_resume(struct device *dev) | |||
794 | { | 829 | { |
795 | struct serio *serio = to_serio_port(dev); | 830 | struct serio *serio = to_serio_port(dev); |
796 | 831 | ||
797 | if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { | 832 | if (serio_reconnect_driver(serio)) { |
798 | /* | 833 | /* |
799 | * Driver re-probing can take a while, so better let kseriod | 834 | * Driver re-probing can take a while, so better let kseriod |
800 | * deal with it. | 835 | * deal with it. |
@@ -848,9 +883,10 @@ irqreturn_t serio_interrupt(struct serio *serio, | |||
848 | 883 | ||
849 | static int __init serio_init(void) | 884 | static int __init serio_init(void) |
850 | { | 885 | { |
851 | if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) { | 886 | serio_task = kthread_run(serio_thread, NULL, "kseriod"); |
887 | if (IS_ERR(serio_task)) { | ||
852 | printk(KERN_ERR "serio: Failed to start kseriod\n"); | 888 | printk(KERN_ERR "serio: Failed to start kseriod\n"); |
853 | return -1; | 889 | return PTR_ERR(serio_task); |
854 | } | 890 | } |
855 | 891 | ||
856 | serio_bus.dev_attrs = serio_device_attrs; | 892 | serio_bus.dev_attrs = serio_device_attrs; |
@@ -866,8 +902,7 @@ static int __init serio_init(void) | |||
866 | static void __exit serio_exit(void) | 902 | static void __exit serio_exit(void) |
867 | { | 903 | { |
868 | bus_unregister(&serio_bus); | 904 | bus_unregister(&serio_bus); |
869 | kill_proc(serio_pid, SIGTERM, 1); | 905 | kthread_stop(serio_task); |
870 | wait_for_completion(&serio_exited); | ||
871 | } | 906 | } |
872 | 907 | ||
873 | module_init(serio_init); | 908 | module_init(serio_init); |
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 546ce599334e..3cdc9cab688d 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c | |||
@@ -226,7 +226,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) | |||
226 | input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0); | 226 | input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0); |
227 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0); | 227 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0); |
228 | break; | 228 | break; |
229 | 229 | ||
230 | case 1: /* 6-byte protocol */ | 230 | case 1: /* 6-byte protocol */ |
231 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0); | 231 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0); |
232 | 232 | ||
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index acb9137a0226..bcfa1e36f957 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
@@ -89,9 +89,9 @@ MODULE_LICENSE("GPL"); | |||
89 | #define H3600_SCANCODE_Q 4 /* 4 -> Q button */ | 89 | #define H3600_SCANCODE_Q 4 /* 4 -> Q button */ |
90 | #define H3600_SCANCODE_START 5 /* 5 -> start menu */ | 90 | #define H3600_SCANCODE_START 5 /* 5 -> start menu */ |
91 | #define H3600_SCANCODE_UP 6 /* 6 -> up */ | 91 | #define H3600_SCANCODE_UP 6 /* 6 -> up */ |
92 | #define H3600_SCANCODE_RIGHT 7 /* 7 -> right */ | 92 | #define H3600_SCANCODE_RIGHT 7 /* 7 -> right */ |
93 | #define H3600_SCANCODE_LEFT 8 /* 8 -> left */ | 93 | #define H3600_SCANCODE_LEFT 8 /* 8 -> left */ |
94 | #define H3600_SCANCODE_DOWN 9 /* 9 -> down */ | 94 | #define H3600_SCANCODE_DOWN 9 /* 9 -> down */ |
95 | 95 | ||
96 | static char *h3600_name = "H3600 TouchScreen"; | 96 | static char *h3600_name = "H3600 TouchScreen"; |
97 | 97 | ||
@@ -113,7 +113,7 @@ struct h3600_dev { | |||
113 | 113 | ||
114 | static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *regs) | 114 | static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *regs) |
115 | { | 115 | { |
116 | int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; | 116 | int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; |
117 | struct input_dev *dev = (struct input_dev *) dev_id; | 117 | struct input_dev *dev = (struct input_dev *) dev_id; |
118 | 118 | ||
119 | input_regs(dev, regs); | 119 | input_regs(dev, regs); |
@@ -125,7 +125,7 @@ static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs * | |||
125 | 125 | ||
126 | static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *regs) | 126 | static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *regs) |
127 | { | 127 | { |
128 | int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; | 128 | int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; |
129 | struct input_dev *dev = (struct input_dev *) dev_id; | 129 | struct input_dev *dev = (struct input_dev *) dev_id; |
130 | 130 | ||
131 | /* | 131 | /* |
@@ -145,8 +145,8 @@ static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs * | |||
145 | static int flite_brightness = 25; | 145 | static int flite_brightness = 25; |
146 | 146 | ||
147 | enum flite_pwr { | 147 | enum flite_pwr { |
148 | FLITE_PWR_OFF = 0, | 148 | FLITE_PWR_OFF = 0, |
149 | FLITE_PWR_ON = 1 | 149 | FLITE_PWR_ON = 1 |
150 | }; | 150 | }; |
151 | 151 | ||
152 | /* | 152 | /* |
@@ -157,9 +157,9 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) | |||
157 | struct h3600_dev *ts = dev->private; | 157 | struct h3600_dev *ts = dev->private; |
158 | 158 | ||
159 | /* Must be in this order */ | 159 | /* Must be in this order */ |
160 | ts->serio->write(ts->serio, 1); | 160 | ts->serio->write(ts->serio, 1); |
161 | ts->serio->write(ts->serio, pwr); | 161 | ts->serio->write(ts->serio, pwr); |
162 | ts->serio->write(ts->serio, brightness); | 162 | ts->serio->write(ts->serio, brightness); |
163 | return 0; | 163 | return 0; |
164 | } | 164 | } |
165 | 165 | ||
@@ -169,26 +169,26 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, | |||
169 | { | 169 | { |
170 | struct input_dev *dev = (struct input_dev *) data; | 170 | struct input_dev *dev = (struct input_dev *) data; |
171 | 171 | ||
172 | switch (req) { | 172 | switch (req) { |
173 | case PM_SUSPEND: /* enter D1-D3 */ | 173 | case PM_SUSPEND: /* enter D1-D3 */ |
174 | suspended = 1; | 174 | suspended = 1; |
175 | h3600_flite_power(dev, FLITE_PWR_OFF); | 175 | h3600_flite_power(dev, FLITE_PWR_OFF); |
176 | break; | 176 | break; |
177 | case PM_BLANK: | 177 | case PM_BLANK: |
178 | if (!suspended) | 178 | if (!suspended) |
179 | h3600_flite_power(dev, FLITE_PWR_OFF); | 179 | h3600_flite_power(dev, FLITE_PWR_OFF); |
180 | break; | 180 | break; |
181 | case PM_RESUME: /* enter D0 */ | 181 | case PM_RESUME: /* enter D0 */ |
182 | /* same as unblank */ | 182 | /* same as unblank */ |
183 | case PM_UNBLANK: | 183 | case PM_UNBLANK: |
184 | if (suspended) { | 184 | if (suspended) { |
185 | //initSerial(); | 185 | //initSerial(); |
186 | suspended = 0; | 186 | suspended = 0; |
187 | } | 187 | } |
188 | h3600_flite_power(dev, FLITE_PWR_ON); | 188 | h3600_flite_power(dev, FLITE_PWR_ON); |
189 | break; | 189 | break; |
190 | } | 190 | } |
191 | return 0; | 191 | return 0; |
192 | } | 192 | } |
193 | #endif | 193 | #endif |
194 | 194 | ||
@@ -199,25 +199,25 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, | |||
199 | */ | 199 | */ |
200 | static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | 200 | static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) |
201 | { | 201 | { |
202 | struct input_dev *dev = &ts->dev; | 202 | struct input_dev *dev = &ts->dev; |
203 | static int touched = 0; | 203 | static int touched = 0; |
204 | int key, down = 0; | 204 | int key, down = 0; |
205 | 205 | ||
206 | input_regs(dev, regs); | 206 | input_regs(dev, regs); |
207 | 207 | ||
208 | switch (ts->event) { | 208 | switch (ts->event) { |
209 | /* | 209 | /* |
210 | Buttons - returned as a single byte | 210 | Buttons - returned as a single byte |
211 | 7 6 5 4 3 2 1 0 | 211 | 7 6 5 4 3 2 1 0 |
212 | S x x x N N N N | 212 | S x x x N N N N |
213 | 213 | ||
214 | S switch state ( 0=pressed 1=released) | 214 | S switch state ( 0=pressed 1=released) |
215 | x Unused. | 215 | x Unused. |
216 | NNNN switch number 0-15 | 216 | NNNN switch number 0-15 |
217 | 217 | ||
218 | Note: This is true for non interrupt generated key events. | 218 | Note: This is true for non interrupt generated key events. |
219 | */ | 219 | */ |
220 | case KEYBD_ID: | 220 | case KEYBD_ID: |
221 | down = (ts->buf[0] & 0x80) ? 0 : 1; | 221 | down = (ts->buf[0] & 0x80) ? 0 : 1; |
222 | 222 | ||
223 | switch (ts->buf[0] & 0x7f) { | 223 | switch (ts->buf[0] & 0x7f) { |
@@ -229,40 +229,40 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | |||
229 | break; | 229 | break; |
230 | case H3600_SCANCODE_CONTACTS: | 230 | case H3600_SCANCODE_CONTACTS: |
231 | key = KEY_PROG2; | 231 | key = KEY_PROG2; |
232 | break; | 232 | break; |
233 | case H3600_SCANCODE_Q: | 233 | case H3600_SCANCODE_Q: |
234 | key = KEY_Q; | 234 | key = KEY_Q; |
235 | break; | 235 | break; |
236 | case H3600_SCANCODE_START: | 236 | case H3600_SCANCODE_START: |
237 | key = KEY_PROG3; | 237 | key = KEY_PROG3; |
238 | break; | 238 | break; |
239 | case H3600_SCANCODE_UP: | 239 | case H3600_SCANCODE_UP: |
240 | key = KEY_UP; | 240 | key = KEY_UP; |
241 | break; | 241 | break; |
242 | case H3600_SCANCODE_RIGHT: | 242 | case H3600_SCANCODE_RIGHT: |
243 | key = KEY_RIGHT; | 243 | key = KEY_RIGHT; |
244 | break; | 244 | break; |
245 | case H3600_SCANCODE_LEFT: | 245 | case H3600_SCANCODE_LEFT: |
246 | key = KEY_LEFT; | 246 | key = KEY_LEFT; |
247 | break; | 247 | break; |
248 | case H3600_SCANCODE_DOWN: | 248 | case H3600_SCANCODE_DOWN: |
249 | key = KEY_DOWN; | 249 | key = KEY_DOWN; |
250 | break; | 250 | break; |
251 | default: | 251 | default: |
252 | key = 0; | 252 | key = 0; |
253 | } | 253 | } |
254 | if (key) | 254 | if (key) |
255 | input_report_key(dev, key, down); | 255 | input_report_key(dev, key, down); |
256 | break; | 256 | break; |
257 | /* | 257 | /* |
258 | * Native touchscreen event data is formatted as shown below:- | 258 | * Native touchscreen event data is formatted as shown below:- |
259 | * | 259 | * |
260 | * +-------+-------+-------+-------+ | 260 | * +-------+-------+-------+-------+ |
261 | * | Xmsb | Xlsb | Ymsb | Ylsb | | 261 | * | Xmsb | Xlsb | Ymsb | Ylsb | |
262 | * +-------+-------+-------+-------+ | 262 | * +-------+-------+-------+-------+ |
263 | * byte 0 1 2 3 | 263 | * byte 0 1 2 3 |
264 | */ | 264 | */ |
265 | case TOUCHS_ID: | 265 | case TOUCHS_ID: |
266 | if (!touched) { | 266 | if (!touched) { |
267 | input_report_key(dev, BTN_TOUCH, 1); | 267 | input_report_key(dev, BTN_TOUCH, 1); |
268 | touched = 1; | 268 | touched = 1; |
@@ -272,19 +272,19 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | |||
272 | unsigned short x, y; | 272 | unsigned short x, y; |
273 | 273 | ||
274 | x = ts->buf[0]; x <<= 8; x += ts->buf[1]; | 274 | x = ts->buf[0]; x <<= 8; x += ts->buf[1]; |
275 | y = ts->buf[2]; y <<= 8; y += ts->buf[3]; | 275 | y = ts->buf[2]; y <<= 8; y += ts->buf[3]; |
276 | 276 | ||
277 | input_report_abs(dev, ABS_X, x); | 277 | input_report_abs(dev, ABS_X, x); |
278 | input_report_abs(dev, ABS_Y, y); | 278 | input_report_abs(dev, ABS_Y, y); |
279 | } else { | 279 | } else { |
280 | input_report_key(dev, BTN_TOUCH, 0); | 280 | input_report_key(dev, BTN_TOUCH, 0); |
281 | touched = 0; | 281 | touched = 0; |
282 | } | 282 | } |
283 | break; | 283 | break; |
284 | default: | 284 | default: |
285 | /* Send a non input event elsewhere */ | 285 | /* Send a non input event elsewhere */ |
286 | break; | 286 | break; |
287 | } | 287 | } |
288 | 288 | ||
289 | input_sync(dev); | 289 | input_sync(dev); |
290 | } | 290 | } |
@@ -293,7 +293,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | |||
293 | * h3600ts_event() handles events from the input module. | 293 | * h3600ts_event() handles events from the input module. |
294 | */ | 294 | */ |
295 | static int h3600ts_event(struct input_dev *dev, unsigned int type, | 295 | static int h3600ts_event(struct input_dev *dev, unsigned int type, |
296 | unsigned int code, int value) | 296 | unsigned int code, int value) |
297 | { | 297 | { |
298 | struct h3600_dev *ts = dev->private; | 298 | struct h3600_dev *ts = dev->private; |
299 | 299 | ||
@@ -332,41 +332,41 @@ static int state; | |||
332 | static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data, | 332 | static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data, |
333 | unsigned int flags, struct pt_regs *regs) | 333 | unsigned int flags, struct pt_regs *regs) |
334 | { | 334 | { |
335 | struct h3600_dev *ts = serio_get_drvdata(serio); | 335 | struct h3600_dev *ts = serio_get_drvdata(serio); |
336 | 336 | ||
337 | /* | 337 | /* |
338 | * We have a new frame coming in. | 338 | * We have a new frame coming in. |
339 | */ | 339 | */ |
340 | switch (state) { | 340 | switch (state) { |
341 | case STATE_SOF: | 341 | case STATE_SOF: |
342 | if (data == CHAR_SOF) | 342 | if (data == CHAR_SOF) |
343 | state = STATE_ID; | 343 | state = STATE_ID; |
344 | break; | 344 | break; |
345 | case STATE_ID: | 345 | case STATE_ID: |
346 | ts->event = (data & 0xf0) >> 4; | 346 | ts->event = (data & 0xf0) >> 4; |
347 | ts->len = (data & 0xf); | 347 | ts->len = (data & 0xf); |
348 | ts->idx = 0; | 348 | ts->idx = 0; |
349 | if (ts->event >= MAX_ID) { | 349 | if (ts->event >= MAX_ID) { |
350 | state = STATE_SOF; | 350 | state = STATE_SOF; |
351 | break; | 351 | break; |
352 | } | 352 | } |
353 | ts->chksum = data; | 353 | ts->chksum = data; |
354 | state = (ts->len > 0) ? STATE_DATA : STATE_EOF; | 354 | state = (ts->len > 0) ? STATE_DATA : STATE_EOF; |
355 | break; | 355 | break; |
356 | case STATE_DATA: | 356 | case STATE_DATA: |
357 | ts->chksum += data; | 357 | ts->chksum += data; |
358 | ts->buf[ts->idx]= data; | 358 | ts->buf[ts->idx]= data; |
359 | if(++ts->idx == ts->len) | 359 | if (++ts->idx == ts->len) |
360 | state = STATE_EOF; | 360 | state = STATE_EOF; |
361 | break; | 361 | break; |
362 | case STATE_EOF: | 362 | case STATE_EOF: |
363 | state = STATE_SOF; | 363 | state = STATE_SOF; |
364 | if (data == CHAR_EOF || data == ts->chksum) | 364 | if (data == CHAR_EOF || data == ts->chksum) |
365 | h3600ts_process_packet(ts, regs); | 365 | h3600ts_process_packet(ts, regs); |
366 | break; | 366 | break; |
367 | default: | 367 | default: |
368 | printk("Error3\n"); | 368 | printk("Error3\n"); |
369 | break; | 369 | break; |
370 | } | 370 | } |
371 | 371 | ||
372 | return IRQ_HANDLED; | 372 | return IRQ_HANDLED; |
@@ -390,10 +390,10 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
390 | init_input_dev(&ts->dev); | 390 | init_input_dev(&ts->dev); |
391 | 391 | ||
392 | /* Device specific stuff */ | 392 | /* Device specific stuff */ |
393 | set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES); | 393 | set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES); |
394 | set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); | 394 | set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); |
395 | 395 | ||
396 | if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, | 396 | if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, |
397 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, | 397 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, |
398 | "h3600_action", &ts->dev)) { | 398 | "h3600_action", &ts->dev)) { |
399 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); | 399 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); |
@@ -401,7 +401,7 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
401 | return -EBUSY; | 401 | return -EBUSY; |
402 | } | 402 | } |
403 | 403 | ||
404 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, | 404 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, |
405 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, | 405 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, |
406 | "h3600_suspend", &ts->dev)) { | 406 | "h3600_suspend", &ts->dev)) { |
407 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); | 407 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); |
@@ -433,7 +433,7 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
433 | 433 | ||
434 | sprintf(ts->phys, "%s/input0", serio->phys); | 434 | sprintf(ts->phys, "%s/input0", serio->phys); |
435 | 435 | ||
436 | ts->dev.event = h3600ts_event; | 436 | ts->dev.event = h3600ts_event; |
437 | ts->dev.private = ts; | 437 | ts->dev.private = ts; |
438 | ts->dev.name = h3600_name; | 438 | ts->dev.name = h3600_name; |
439 | ts->dev.phys = ts->phys; | 439 | ts->dev.phys = ts->phys; |
@@ -446,8 +446,8 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
446 | 446 | ||
447 | err = serio_open(serio, drv); | 447 | err = serio_open(serio, drv); |
448 | if (err) { | 448 | if (err) { |
449 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts); | 449 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts); |
450 | free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts); | 450 | free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts); |
451 | serio_set_drvdata(serio, NULL); | 451 | serio_set_drvdata(serio, NULL); |
452 | kfree(ts); | 452 | kfree(ts); |
453 | return err; | 453 | return err; |
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c index 2d14a57a05e5..afaaebe5225b 100644 --- a/drivers/input/touchscreen/mk712.c +++ b/drivers/input/touchscreen/mk712.c | |||
@@ -17,7 +17,7 @@ | |||
17 | * found in Gateway AOL Connected Touchpad computers. | 17 | * found in Gateway AOL Connected Touchpad computers. |
18 | * | 18 | * |
19 | * Documentation for ICS MK712 can be found at: | 19 | * Documentation for ICS MK712 can be found at: |
20 | * http://www.icst.com/pdf/mk712.pdf | 20 | * http://www.icst.com/pdf/mk712.pdf |
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* | 23 | /* |
@@ -77,7 +77,6 @@ MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller"); | |||
77 | #define MK712_READ_ONE_POINT 0x20 | 77 | #define MK712_READ_ONE_POINT 0x20 |
78 | #define MK712_POWERUP 0x40 | 78 | #define MK712_POWERUP 0x40 |
79 | 79 | ||
80 | static int mk712_used = 0; | ||
81 | static struct input_dev mk712_dev; | 80 | static struct input_dev mk712_dev; |
82 | static DEFINE_SPINLOCK(mk712_lock); | 81 | static DEFINE_SPINLOCK(mk712_lock); |
83 | 82 | ||
@@ -130,17 +129,14 @@ static int mk712_open(struct input_dev *dev) | |||
130 | 129 | ||
131 | spin_lock_irqsave(&mk712_lock, flags); | 130 | spin_lock_irqsave(&mk712_lock, flags); |
132 | 131 | ||
133 | if (!mk712_used++) { | 132 | outb(0, mk712_io + MK712_CONTROL); /* Reset */ |
134 | 133 | ||
135 | outb(0, mk712_io + MK712_CONTROL); /* Reset */ | 134 | outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE | |
135 | MK712_INT_ON_CHANGE_IN_TOUCH_STATUS | | ||
136 | MK712_ENABLE_PERIODIC_CONVERSIONS | | ||
137 | MK712_POWERUP, mk712_io + MK712_CONTROL); | ||
136 | 138 | ||
137 | outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE | | 139 | outb(10, mk712_io + MK712_RATE); /* 187 points per second */ |
138 | MK712_INT_ON_CHANGE_IN_TOUCH_STATUS | | ||
139 | MK712_ENABLE_PERIODIC_CONVERSIONS | | ||
140 | MK712_POWERUP, mk712_io + MK712_CONTROL); | ||
141 | |||
142 | outb(10, mk712_io + MK712_RATE); /* 187 points per second */ | ||
143 | } | ||
144 | 140 | ||
145 | spin_unlock_irqrestore(&mk712_lock, flags); | 141 | spin_unlock_irqrestore(&mk712_lock, flags); |
146 | 142 | ||
@@ -153,8 +149,7 @@ static void mk712_close(struct input_dev *dev) | |||
153 | 149 | ||
154 | spin_lock_irqsave(&mk712_lock, flags); | 150 | spin_lock_irqsave(&mk712_lock, flags); |
155 | 151 | ||
156 | if (!--mk712_used) | 152 | outb(0, mk712_io + MK712_CONTROL); |
157 | outb(0, mk712_io + MK712_CONTROL); | ||
158 | 153 | ||
159 | spin_unlock_irqrestore(&mk712_lock, flags); | 154 | spin_unlock_irqrestore(&mk712_lock, flags); |
160 | } | 155 | } |