diff options
-rw-r--r-- | Documentation/input/appletouch.txt | 5 | ||||
-rw-r--r-- | drivers/input/evdev.c | 493 | ||||
-rw-r--r-- | drivers/input/gameport/Kconfig | 7 | ||||
-rw-r--r-- | drivers/input/misc/m68kspkr.c | 102 | ||||
-rw-r--r-- | drivers/input/misc/pcspkr.c | 86 | ||||
-rw-r--r-- | drivers/input/misc/sparcspkr.c | 162 | ||||
-rw-r--r-- | drivers/input/misc/wistron_btns.c | 133 | ||||
-rw-r--r-- | drivers/input/mouse/alps.c | 1 | ||||
-rw-r--r-- | drivers/input/mouse/lifebook.c | 7 | ||||
-rw-r--r-- | drivers/input/mouse/logips2pp.c | 2 | ||||
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 15 | ||||
-rw-r--r-- | drivers/input/mousedev.c | 10 | ||||
-rw-r--r-- | drivers/input/serio/ct82c710.c | 89 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 7 | ||||
-rw-r--r-- | drivers/input/serio/i8042.c | 116 | ||||
-rw-r--r-- | drivers/input/serio/maceps2.c | 68 | ||||
-rw-r--r-- | drivers/input/serio/q40kbd.c | 89 | ||||
-rw-r--r-- | drivers/usb/input/appletouch.c | 145 | ||||
-rw-r--r-- | drivers/usb/input/hid-debug.h | 1 |
19 files changed, 957 insertions, 581 deletions
diff --git a/Documentation/input/appletouch.txt b/Documentation/input/appletouch.txt index b48d11d0326d..4f7c633a76d2 100644 --- a/Documentation/input/appletouch.txt +++ b/Documentation/input/appletouch.txt @@ -3,7 +3,7 @@ Apple Touchpad Driver (appletouch) Copyright (C) 2005 Stelian Pop <stelian@popies.net> appletouch is a Linux kernel driver for the USB touchpad found on post -February 2005 Apple Alu Powerbooks. +February 2005 and October 2005 Apple Aluminium Powerbooks. This driver is derived from Johannes Berg's appletrackpad driver[1], but it has been improved in some areas: @@ -13,7 +13,8 @@ been improved in some areas: Credits go to Johannes Berg for reverse-engineering the touchpad protocol, Frank Arnold for further improvements, and Alex Harper for some additional -information about the inner workings of the touchpad sensors. +information about the inner workings of the touchpad sensors. Michael +Hanselmann added support for the October 2005 models. Usage: ------ diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 9f2352bd8348..0270d1ec9425 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -146,6 +146,7 @@ static int evdev_open(struct inode * inode, struct file * file) } #ifdef CONFIG_COMPAT + struct input_event_compat { struct compat_timeval time; __u16 type; @@ -165,98 +166,107 @@ struct input_event_compat { # define COMPAT_TEST test_thread_flag(TIF_32BIT) #endif -static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) +static inline size_t evdev_event_size(void) { - struct evdev_list *list = file->private_data; - struct input_event_compat event; - int retval = 0; + return COMPAT_TEST ? + sizeof(struct input_event_compat) : sizeof(struct input_event); +} - while (retval < count) { - if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat))) +static int evdev_event_from_user(const char __user *buffer, struct input_event *event) +{ + if (COMPAT_TEST) { + struct input_event_compat compat_event; + + if (copy_from_user(&compat_event, buffer, sizeof(struct input_event_compat))) + return -EFAULT; + + event->time.tv_sec = compat_event.time.tv_sec; + event->time.tv_usec = compat_event.time.tv_usec; + event->type = compat_event.type; + event->code = compat_event.code; + event->value = compat_event.value; + + } else { + if (copy_from_user(event, buffer, sizeof(struct input_event))) return -EFAULT; - input_event(list->evdev->handle.dev, event.type, event.code, event.value); - retval += sizeof(struct input_event_compat); } - return retval; + return 0; } -#endif -static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) +static int evdev_event_to_user(char __user *buffer, const struct input_event *event) { - struct evdev_list *list = file->private_data; - struct input_event event; - int retval = 0; - - if (!list->evdev->exist) return -ENODEV; + if (COMPAT_TEST) { + struct input_event_compat compat_event; -#ifdef CONFIG_COMPAT - if (COMPAT_TEST) - return evdev_write_compat(file, buffer, count, ppos); -#endif + compat_event.time.tv_sec = event->time.tv_sec; + compat_event.time.tv_usec = event->time.tv_usec; + compat_event.type = event->type; + compat_event.code = event->code; + compat_event.value = event->value; - while (retval < count) { + if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat))) + return -EFAULT; - if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) + } else { + if (copy_to_user(buffer, event, sizeof(struct input_event))) return -EFAULT; - input_event(list->evdev->handle.dev, event.type, event.code, event.value); - retval += sizeof(struct input_event); } - return retval; + return 0; } -#ifdef CONFIG_COMPAT -static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos) +#else + +static inline size_t evdev_event_size(void) { - struct evdev_list *list = file->private_data; - int retval; + return sizeof(struct input_event); +} - if (count < sizeof(struct input_event_compat)) - return -EINVAL; +static int evdev_event_from_user(const char __user *buffer, struct input_event *event) +{ + if (copy_from_user(event, buffer, sizeof(struct input_event))) + return -EFAULT; - if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) - return -EAGAIN; + return 0; +} - retval = wait_event_interruptible(list->evdev->wait, - list->head != list->tail || (!list->evdev->exist)); +static int evdev_event_to_user(char __user *buffer, const struct input_event *event) +{ + if (copy_to_user(buffer, event, sizeof(struct input_event))) + return -EFAULT; - if (retval) - return retval; + return 0; +} + +#endif /* CONFIG_COMPAT */ + +static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) +{ + struct evdev_list *list = file->private_data; + struct input_event event; + int retval = 0; if (!list->evdev->exist) return -ENODEV; - while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) { - struct input_event *event = (struct input_event *) list->buffer + list->tail; - struct input_event_compat event_compat; - event_compat.time.tv_sec = event->time.tv_sec; - event_compat.time.tv_usec = event->time.tv_usec; - event_compat.type = event->type; - event_compat.code = event->code; - event_compat.value = event->value; - - if (copy_to_user(buffer + retval, &event_compat, - sizeof(struct input_event_compat))) return -EFAULT; - list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); - retval += sizeof(struct input_event_compat); + while (retval < count) { + + if (evdev_event_from_user(buffer + retval, &event)) + return -EFAULT; + input_event(list->evdev->handle.dev, event.type, event.code, event.value); + retval += evdev_event_size(); } return retval; } -#endif static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; int retval; -#ifdef CONFIG_COMPAT - if (COMPAT_TEST) - return evdev_read_compat(file, buffer, count, ppos); -#endif - - if (count < sizeof(struct input_event)) + if (count < evdev_event_size()) return -EINVAL; if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) @@ -271,11 +281,15 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count if (!list->evdev->exist) return -ENODEV; - while (list->head != list->tail && retval + sizeof(struct input_event) <= count) { - if (copy_to_user(buffer + retval, list->buffer + list->tail, - sizeof(struct input_event))) return -EFAULT; + while (list->head != list->tail && retval + evdev_event_size() <= count) { + + struct input_event *event = (struct input_event *) list->buffer + list->tail; + + if (evdev_event_to_user(buffer + retval, event)) + return -EFAULT; + list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); - retval += sizeof(struct input_event); + retval += evdev_event_size(); } return retval; @@ -290,17 +304,95 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait) (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); } -static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +#ifdef CONFIG_COMPAT + +#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) +#define NBITS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1) + +#ifdef __BIG_ENDIAN +static int bits_to_user(unsigned long *bits, unsigned int maxbit, + unsigned int maxlen, void __user *p, int compat) +{ + int len, i; + + if (compat) { + len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t); + if (len < maxlen) + len = maxlen; + + for (i = 0; i < len / sizeof(compat_long_t); i++) + if (copy_to_user((compat_long_t __user *) p + i, + (compat_long_t *) bits + + i + 1 - ((i % 2) << 1), + sizeof(compat_long_t))) + return -EFAULT; + } else { + len = NBITS(maxbit) * sizeof(long); + if (len > maxlen) + len = maxlen; + + if (copy_to_user(p, bits, len)) + return -EFAULT; + } + + return len; +} +#else +static int bits_to_user(unsigned long *bits, unsigned int maxbit, + unsigned int maxlen, void __user *p, int compat) +{ + int len = compat ? + NBITS_COMPAT(maxbit) * sizeof(compat_long_t) : + NBITS(maxbit) * sizeof(long); + + if (len > maxlen) + len = maxlen; + + return copy_to_user(p, bits, len) ? -EFAULT : len; +} +#endif /* __BIG_ENDIAN */ + +#else + +static int bits_to_user(unsigned long *bits, unsigned int maxbit, + unsigned int maxlen, void __user *p, int compat) +{ + int len = NBITS(maxbit) * sizeof(long); + + if (len > maxlen) + len = maxlen; + + return copy_to_user(p, bits, len) ? -EFAULT : len; +} + +#endif /* CONFIG_COMPAT */ + +static int str_to_user(const char *str, unsigned int maxlen, void __user *p) +{ + int len; + + if (!str) + return -ENOENT; + + len = strlen(str) + 1; + if (len > maxlen) + len = maxlen; + + return copy_to_user(p, str, len) ? -EFAULT : len; +} + +static long evdev_ioctl_handler(struct file *file, unsigned int cmd, + void __user *p, int compat_mode) { struct evdev_list *list = file->private_data; struct evdev *evdev = list->evdev; struct input_dev *dev = evdev->handle.dev; struct input_absinfo abs; - void __user *p = (void __user *)arg; - int __user *ip = (int __user *)arg; + int __user *ip = (int __user *)p; int i, t, u, v; - if (!evdev->exist) return -ENODEV; + if (!evdev->exist) + return -ENODEV; switch (cmd) { @@ -308,26 +400,39 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return put_user(EV_VERSION, ip); case EVIOCGID: - return copy_to_user(p, &dev->id, sizeof(struct input_id)) ? -EFAULT : 0; + if (copy_to_user(p, &dev->id, sizeof(struct input_id))) + return -EFAULT; + + return 0; case EVIOCGKEYCODE: - if (get_user(t, ip)) return -EFAULT; - if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL; - if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) return -EFAULT; + if (get_user(t, ip)) + return -EFAULT; + if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) + return -EINVAL; + if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) + return -EFAULT; return 0; case EVIOCSKEYCODE: - if (get_user(t, ip)) return -EFAULT; - if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL; - if (get_user(v, ip + 1)) return -EFAULT; - if (v < 0 || v > KEY_MAX) return -EINVAL; - if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL; + if (get_user(t, ip)) + return -EFAULT; + if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) + return -EINVAL; + if (get_user(v, ip + 1)) + return -EFAULT; + if (v < 0 || v > KEY_MAX) + return -EINVAL; + if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) + return -EINVAL; + u = SET_INPUT_KEYCODE(dev, t, v); clear_bit(u, dev->keybit); set_bit(v, dev->keybit); for (i = 0; i < dev->keycodemax; i++) - if (INPUT_KEYCODE(dev,i) == u) + if (INPUT_KEYCODE(dev, i) == u) set_bit(u, dev->keybit); + return 0; case EVIOCSFF: @@ -338,17 +443,17 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (copy_from_user(&effect, p, sizeof(effect))) return -EFAULT; err = dev->upload_effect(dev, &effect); - if (put_user(effect.id, &(((struct ff_effect __user *)arg)->id))) + if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) return -EFAULT; return err; - } - else return -ENOSYS; + } else + return -ENOSYS; case EVIOCRMFF: - if (dev->erase_effect) { - return dev->erase_effect(dev, (int)arg); - } - else return -ENOSYS; + if (!dev->erase_effect) + return -ENOSYS; + + return dev->erase_effect(dev, (int)(unsigned long) p); case EVIOCGEFFECTS: if (put_user(dev->ff_effects_max, ip)) @@ -356,7 +461,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; case EVIOCGRAB: - if (arg) { + if (p) { if (evdev->grab) return -EBUSY; if (input_grab_device(&evdev->handle)) @@ -395,62 +500,33 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case EV_SW: bits = dev->swbit; len = SW_MAX; break; default: return -EINVAL; } - len = NBITS(len) * sizeof(long); - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, bits, len) ? -EFAULT : len; + return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); } - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { - int len; - len = NBITS(KEY_MAX) * sizeof(long); - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->key, len) ? -EFAULT : len; - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) + return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), + p, compat_mode); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { - int len; - len = NBITS(LED_MAX) * sizeof(long); - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->led, len) ? -EFAULT : len; - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) + return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), + p, compat_mode); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { - int len; - len = NBITS(SND_MAX) * sizeof(long); - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->snd, len) ? -EFAULT : len; - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) + return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), + p, compat_mode); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) { - int len; - len = NBITS(SW_MAX) * sizeof(long); - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->sw, len) ? -EFAULT : len; - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) + return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), + p, compat_mode); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { - int len; - if (!dev->name) return -ENOENT; - len = strlen(dev->name) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->name, len) ? -EFAULT : len; - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) + return str_to_user(dev->name, _IOC_SIZE(cmd), p); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { - int len; - if (!dev->phys) return -ENOENT; - len = strlen(dev->phys) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->phys, len) ? -EFAULT : len; - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) + return str_to_user(dev->phys, _IOC_SIZE(cmd), p); - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { - int len; - if (!dev->uniq) return -ENOENT; - len = strlen(dev->uniq) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; - } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) + return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { @@ -492,158 +568,15 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EINVAL; } -#ifdef CONFIG_COMPAT - -#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) -#define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1) -#define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT) -#define BIT_COMPAT(x) (1UL<<OFF_COMPAT(x)) -#define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT) -#define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1) - -#ifdef __BIG_ENDIAN -#define bit_to_user(bit, max) \ -do { \ - int i; \ - int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ - for (i = 0; i < len / sizeof(compat_long_t); i++) \ - if (copy_to_user((compat_long_t __user *) p + i, \ - (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \ - sizeof(compat_long_t))) \ - return -EFAULT; \ - return len; \ -} while (0) -#else -#define bit_to_user(bit, max) \ -do { \ - int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ - return copy_to_user(p, (bit), len) ? -EFAULT : len; \ -} while (0) -#endif +static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0); +} +#ifdef CONFIG_COMPAT static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) { - struct evdev_list *list = file->private_data; - struct evdev *evdev = list->evdev; - struct input_dev *dev = evdev->handle.dev; - struct input_absinfo abs; - void __user *p = compat_ptr(arg); - - if (!evdev->exist) return -ENODEV; - - switch (cmd) { - - case EVIOCGVERSION: - case EVIOCGID: - case EVIOCGKEYCODE: - case EVIOCSKEYCODE: - case EVIOCSFF: - case EVIOCRMFF: - case EVIOCGEFFECTS: - case EVIOCGRAB: - return evdev_ioctl(file, cmd, (unsigned long) p); - - default: - - if (_IOC_TYPE(cmd) != 'E') - return -EINVAL; - - if (_IOC_DIR(cmd) == _IOC_READ) { - - if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { - long *bits; - int max; - - switch (_IOC_NR(cmd) & EV_MAX) { - case 0: bits = dev->evbit; max = EV_MAX; break; - case EV_KEY: bits = dev->keybit; max = KEY_MAX; break; - case EV_REL: bits = dev->relbit; max = REL_MAX; break; - case EV_ABS: bits = dev->absbit; max = ABS_MAX; break; - case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break; - case EV_LED: bits = dev->ledbit; max = LED_MAX; break; - case EV_SND: bits = dev->sndbit; max = SND_MAX; break; - case EV_FF: bits = dev->ffbit; max = FF_MAX; break; - case EV_SW: bits = dev->swbit; max = SW_MAX; break; - default: return -EINVAL; - } - bit_to_user(bits, max); - } - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) - bit_to_user(dev->key, KEY_MAX); - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) - bit_to_user(dev->led, LED_MAX); - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) - bit_to_user(dev->snd, SND_MAX); - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) - bit_to_user(dev->sw, SW_MAX); - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { - int len; - if (!dev->name) return -ENOENT; - len = strlen(dev->name) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->name, len) ? -EFAULT : len; - } - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { - int len; - if (!dev->phys) return -ENOENT; - len = strlen(dev->phys) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->phys, len) ? -EFAULT : len; - } - - if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { - int len; - if (!dev->uniq) return -ENOENT; - len = strlen(dev->uniq) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; - } - - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { - - int t = _IOC_NR(cmd) & ABS_MAX; - - abs.value = dev->abs[t]; - abs.minimum = dev->absmin[t]; - abs.maximum = dev->absmax[t]; - abs.fuzz = dev->absfuzz[t]; - abs.flat = dev->absflat[t]; - - if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) - return -EFAULT; - - return 0; - } - } - - if (_IOC_DIR(cmd) == _IOC_WRITE) { - - if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { - - int t = _IOC_NR(cmd) & ABS_MAX; - - if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) - return -EFAULT; - - dev->abs[t] = abs.value; - dev->absmin[t] = abs.minimum; - dev->absmax[t] = abs.maximum; - dev->absfuzz[t] = abs.fuzz; - dev->absflat[t] = abs.flat; - - return 0; - } - } - } - return -EINVAL; + return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); } #endif diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig index 7524bd7d8b8f..d279454a5c9e 100644 --- a/drivers/input/gameport/Kconfig +++ b/drivers/input/gameport/Kconfig @@ -52,5 +52,12 @@ config GAMEPORT_EMU10K1 config GAMEPORT_FM801 tristate "ForteMedia FM801 gameport support" depends on PCI + help + Say Y here if you have ForteMedia FM801 PCI audio controller + (Abit AU10, Genius Sound Maker, HP Workstation zx2000, + and others), and want to use its gameport. + + To compile this driver as a module, choose M here: the + module will be called fm801-gp. endif diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c index 04489ad7702a..8d6c3837badb 100644 --- a/drivers/input/misc/m68kspkr.c +++ b/drivers/input/misc/m68kspkr.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/input.h> +#include <linux/platform_device.h> #include <asm/machdep.h> #include <asm/io.h> @@ -24,7 +25,7 @@ MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>"); MODULE_DESCRIPTION("m68k beeper driver"); MODULE_LICENSE("GPL"); -static struct input_dev *m68kspkr_dev; +static struct platform_device *m68kspkr_platform_device; static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { @@ -47,36 +48,103 @@ static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int return 0; } +static int __devinit m68kspkr_probe(struct platform_device *dev) +{ + struct input_dev *input_dev; + int err; + + input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; + + input_dev->name = "m68k beeper"; + input_dev->phys = "m68k/generic"; + input_dev->id.bustype = BUS_HOST; + input_dev->id.vendor = 0x001f; + input_dev->id.product = 0x0001; + input_dev->id.version = 0x0100; + input_dev->cdev.dev = &dev->dev; + + input_dev->evbit[0] = BIT(EV_SND); + input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); + input_dev->event = m68kspkr_event; + + err = input_register_device(input_dev); + if (err) { + input_free_device(input_dev); + return err; + } + + platform_set_drvdata(dev, input_dev); + + return 0; +} + +static int __devexit m68kspkr_remove(struct platform_device *dev) +{ + struct input_dev *input_dev = platform_get_drvdata(dev); + + input_unregister_device(input_dev); + platform_set_drvdata(dev, NULL); + /* turn off the speaker */ + m68kspkr_event(NULL, EV_SND, SND_BELL, 0); + + return 0; +} + +static void m68kspkr_shutdown(struct platform_device *dev) +{ + /* turn off the speaker */ + m68kspkr_event(NULL, EV_SND, SND_BELL, 0); +} + +static struct platform_driver m68kspkr_platform_driver = { + .driver = { + .name = "m68kspkr", + .owner = THIS_MODULE, + }, + .probe = m68kspkr_probe, + .remove = __devexit_p(m68kspkr_remove), + .shutdown = m68kspkr_shutdown, +}; + static int __init m68kspkr_init(void) { - if (!mach_beep) { + int err; + + if (!mach_beep) { printk(KERN_INFO "m68kspkr: no lowlevel beep support\n"); return -ENODEV; } - m68kspkr_dev = input_allocate_device(); - if (!m68kspkr_dev) - return -ENOMEM; - - m68kspkr_dev->name = "m68k beeper"; - m68kspkr_dev->phys = "m68k/generic"; - m68kspkr_dev->id.bustype = BUS_HOST; - m68kspkr_dev->id.vendor = 0x001f; - m68kspkr_dev->id.product = 0x0001; - m68kspkr_dev->id.version = 0x0100; + err = platform_driver_register(&m68kspkr_platform_driver); + if (err) + return err; - m68kspkr_dev->evbit[0] = BIT(EV_SND); - m68kspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); - m68kspkr_dev->event = m68kspkr_event; + m68kspkr_platform_device = platform_device_alloc("m68kspkr", -1); + if (!m68kspkr_platform_device) { + err = -ENOMEM; + goto err_unregister_driver; + } - input_register_device(m68kspkr_dev); + err = platform_device_add(m68kspkr_platform_device); + if (err) + goto err_free_device; return 0; + + err_free_device: + platform_device_put(m68kspkr_platform_device); + err_unregister_driver: + platform_driver_unregister(&m68kspkr_platform_driver); + + return err; } static void __exit m68kspkr_exit(void) { - input_unregister_device(m68kspkr_dev); + platform_device_unregister(m68kspkr_platform_device); + platform_driver_unregister(&m68kspkr_platform_driver); } module_init(m68kspkr_init); diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 68ac97f101b0..1ef477f4469c 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -16,6 +16,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/input.h> +#include <linux/platform_device.h> #include <asm/8253pit.h> #include <asm/io.h> @@ -23,8 +24,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("PC Speaker beeper driver"); MODULE_LICENSE("GPL"); -static struct input_dev *pcspkr_dev; - +static struct platform_device *pcspkr_platform_device; static DEFINE_SPINLOCK(i8253_beep_lock); static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) @@ -64,8 +64,11 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c return 0; } -static int __init pcspkr_init(void) +static int __devinit pcspkr_probe(struct platform_device *dev) { + struct input_dev *pcspkr_dev; + int err; + pcspkr_dev = input_allocate_device(); if (!pcspkr_dev) return -ENOMEM; @@ -76,22 +79,93 @@ static int __init pcspkr_init(void) pcspkr_dev->id.vendor = 0x001f; pcspkr_dev->id.product = 0x0001; pcspkr_dev->id.version = 0x0100; + pcspkr_dev->cdev.dev = &dev->dev; pcspkr_dev->evbit[0] = BIT(EV_SND); pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); pcspkr_dev->event = pcspkr_event; - input_register_device(pcspkr_dev); + err = input_register_device(pcspkr_dev); + if (err) { + input_free_device(pcspkr_dev); + return err; + } + + platform_set_drvdata(dev, pcspkr_dev); return 0; } -static void __exit pcspkr_exit(void) +static int __devexit pcspkr_remove(struct platform_device *dev) +{ + struct input_dev *pcspkr_dev = platform_get_drvdata(dev); + + input_unregister_device(pcspkr_dev); + platform_set_drvdata(dev, NULL); + /* turn off the speaker */ + pcspkr_event(NULL, EV_SND, SND_BELL, 0); + + return 0; +} + +static int pcspkr_suspend(struct platform_device *dev, pm_message_t state) +{ + pcspkr_event(NULL, EV_SND, SND_BELL, 0); + + return 0; +} + +static void pcspkr_shutdown(struct platform_device *dev) { - input_unregister_device(pcspkr_dev); /* turn off the speaker */ pcspkr_event(NULL, EV_SND, SND_BELL, 0); } +static struct platform_driver pcspkr_platform_driver = { + .driver = { + .name = "pcspkr", + .owner = THIS_MODULE, + }, + .probe = pcspkr_probe, + .remove = __devexit_p(pcspkr_remove), + .suspend = pcspkr_suspend, + .shutdown = pcspkr_shutdown, +}; + + +static int __init pcspkr_init(void) +{ + int err; + + err = platform_driver_register(&pcspkr_platform_driver); + if (err) + return err; + + pcspkr_platform_device = platform_device_alloc("pcspkr", -1); + if (!pcspkr_platform_device) { + err = -ENOMEM; + goto err_unregister_driver; + } + + err = platform_device_add(pcspkr_platform_device); + if (err) + goto err_free_device; + + return 0; + + err_free_device: + platform_device_put(pcspkr_platform_device); + err_unregister_driver: + platform_driver_unregister(&pcspkr_platform_driver); + + return err; +} + +static void __exit pcspkr_exit(void) +{ + platform_device_unregister(pcspkr_platform_device); + platform_driver_unregister(&pcspkr_platform_driver); +} + module_init(pcspkr_init); module_exit(pcspkr_exit); diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index 29d97b12be7a..f0fd2c4740f1 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/input.h> +#include <linux/platform_device.h> #include <asm/io.h> #include <asm/ebus.h> @@ -20,22 +21,10 @@ MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); MODULE_DESCRIPTION("Sparc Speaker beeper driver"); MODULE_LICENSE("GPL"); +const char *beep_name; static unsigned long beep_iobase; -static struct input_dev *sparcspkr_dev; - -DEFINE_SPINLOCK(beep_lock); - -static void __init init_sparcspkr_struct(void) -{ - sparcspkr_dev->evbit[0] = BIT(EV_SND); - sparcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); - - sparcspkr_dev->phys = "sparc/input0"; - sparcspkr_dev->id.bustype = BUS_ISA; - sparcspkr_dev->id.vendor = 0x001f; - sparcspkr_dev->id.product = 0x0001; - sparcspkr_dev->id.version = 0x0100; -} +static int (*beep_event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); +static DEFINE_SPINLOCK(beep_lock); static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { @@ -59,39 +48,16 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in /* EBUS speaker only has on/off state, the frequency does not * appear to be programmable. */ - if (count) { - if (beep_iobase & 0x2UL) - outb(1, beep_iobase); - else - outl(1, beep_iobase); - } else { - if (beep_iobase & 0x2UL) - outb(0, beep_iobase); - else - outl(0, beep_iobase); - } + if (beep_iobase & 0x2UL) + outb(!!count, beep_iobase); + else + outl(!!count, beep_iobase); spin_unlock_irqrestore(&beep_lock, flags); return 0; } -static int __init init_ebus_beep(struct linux_ebus_device *edev) -{ - beep_iobase = edev->resource[0].start; - - sparcspkr_dev = input_allocate_device(); - if (!sparcspkr_dev) - return -ENOMEM; - - sparcspkr_dev->name = "Sparc EBUS Speaker"; - sparcspkr_dev->event = ebus_spkr_event; - - input_register_device(sparcspkr_dev); - - return 0; -} - #ifdef CONFIG_SPARC64 static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { @@ -129,30 +95,103 @@ static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int return 0; } +#endif -static int __init init_isa_beep(struct sparc_isa_device *isa_dev) +static int __devinit sparcspkr_probe(struct platform_device *dev) { - beep_iobase = isa_dev->resource.start; + struct input_dev *input_dev; + int error; - sparcspkr_dev = input_allocate_device(); - if (!sparcspkr_dev) + input_dev = input_allocate_device(); + if (!input_dev) return -ENOMEM; - init_sparcspkr_struct(); + input_dev->name = beep_name; + input_dev->phys = "sparc/input0"; + input_dev->id.bustype = BUS_ISA; + input_dev->id.vendor = 0x001f; + input_dev->id.product = 0x0001; + input_dev->id.version = 0x0100; + input_dev->cdev.dev = &dev->dev; - sparcspkr_dev->name = "Sparc ISA Speaker"; - sparcspkr_dev->event = isa_spkr_event; + input_dev->evbit[0] = BIT(EV_SND); + input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); - input_register_device(sparcspkr_dev); + input_dev->event = beep_event; + + error = input_register_device(input_dev); + if (error) { + input_free_device(input_dev); + return error; + } + + platform_set_drvdata(dev, input_dev); return 0; } -#endif + +static int __devexit sparcspkr_remove(struct platform_device *dev) +{ + struct input_dev *input_dev = platform_get_drvdata(dev); + + input_unregister_device(input_dev); + platform_set_drvdata(dev, NULL); + /* turn off the speaker */ + beep_event(NULL, EV_SND, SND_BELL, 0); + + return 0; +} + +static void sparcspkr_shutdown(struct platform_device *dev) +{ + /* turn off the speaker */ + beep_event(NULL, EV_SND, SND_BELL, 0); +} + +static struct platform_driver sparcspkr_platform_driver = { + .driver = { + .name = "sparcspkr", + .owner = THIS_MODULE, + }, + .probe = sparcspkr_probe, + .remove = __devexit_p(sparcspkr_remove), + .shutdown = sparcspkr_shutdown, +}; + +static struct platform_device *sparcspkr_platform_device; + +static int __init sparcspkr_drv_init(void) +{ + int error; + + error = platform_driver_register(&sparcspkr_platform_driver); + if (error) + return error; + + sparcspkr_platform_device = platform_device_alloc("sparcspkr", -1); + if (!sparcspkr_platform_device) { + error = -ENOMEM; + goto err_unregister_driver; + } + + error = platform_device_add(sparcspkr_platform_device); + if (error) + goto err_free_device; + + return 0; + + err_free_device: + platform_device_put(sparcspkr_platform_device); + err_unregister_driver: + platform_driver_unregister(&sparcspkr_platform_driver); + + return error; +} static int __init sparcspkr_init(void) { struct linux_ebus *ebus; - struct linux_ebus_device *edev = NULL; + struct linux_ebus_device *edev; #ifdef CONFIG_SPARC64 struct sparc_isa_bridge *isa_br; struct sparc_isa_device *isa_dev; @@ -160,8 +199,12 @@ static int __init sparcspkr_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "beep")) - return init_ebus_beep(edev); + if (!strcmp(edev->prom_name, "beep")) { + beep_name = "Sparc EBUS Speaker"; + beep_event = ebus_spkr_event; + beep_iobase = edev->resource[0].start; + return sparcspkr_drv_init(); + } } } #ifdef CONFIG_SPARC64 @@ -170,8 +213,12 @@ static int __init sparcspkr_init(void) /* A hack, the beep device's base lives in * the DMA isa node. */ - if (!strcmp(isa_dev->prom_name, "dma")) - return init_isa_beep(isa_dev); + if (!strcmp(isa_dev->prom_name, "dma")) { + beep_name = "Sparc ISA Speaker"; + beep_event = isa_spkr_event, + beep_iobase = isa_dev->resource.start; + return sparcspkr_drv_init(); + } } } #endif @@ -181,7 +228,8 @@ static int __init sparcspkr_init(void) static void __exit sparcspkr_exit(void) { - input_unregister_device(sparcspkr_dev); + platform_device_unregister(sparcspkr_platform_device); + platform_driver_unregister(&sparcspkr_platform_driver); } module_init(sparcspkr_init); diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index bac3085185fe..a05b8557842f 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -174,7 +174,7 @@ static u16 bios_pop_queue(void) return regs.eax; } -static void __init bios_attach(void) +static void __devinit bios_attach(void) { struct regs regs; @@ -194,7 +194,7 @@ static void bios_detach(void) call_bios(®s); } -static u8 __init bios_get_cmos_address(void) +static u8 __devinit bios_get_cmos_address(void) { struct regs regs; @@ -206,7 +206,7 @@ static u8 __init bios_get_cmos_address(void) return regs.ecx; } -static u16 __init bios_get_default_setting(u8 subsys) +static u16 __devinit bios_get_default_setting(u8 subsys) { struct regs regs; @@ -296,6 +296,16 @@ static struct key_entry keymap_acer_aspire_1500[] = { { KE_END, 0 } }; +static struct key_entry keymap_acer_travelmate_240[] = { + { KE_KEY, 0x31, KEY_MAIL }, + { KE_KEY, 0x36, KEY_WWW }, + { KE_KEY, 0x11, KEY_PROG1 }, + { KE_KEY, 0x12, KEY_PROG2 }, + { KE_BLUETOOTH, 0x44, 0 }, + { KE_WIFI, 0x30, 0 }, + { KE_END, 0 } +}; + /* * If your machine is not here (which is currently rather likely), please send * a list of buttons and their key codes (reported when loading this module @@ -320,6 +330,15 @@ static struct dmi_system_id dmi_ids[] = { }, .driver_data = keymap_acer_aspire_1500 }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 240", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"), + }, + .driver_data = keymap_acer_travelmate_240 + }, { NULL, } }; @@ -348,7 +367,7 @@ static int __init select_keymap(void) static struct input_dev *input_dev; -static int __init setup_input_dev(void) +static int __devinit setup_input_dev(void) { const struct key_entry *key; int error; @@ -447,6 +466,52 @@ static void poll_bios(unsigned long discard) mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY); } +static int __devinit wistron_probe(struct platform_device *dev) +{ + int err = setup_input_dev(); + if (err) + return err; + + bios_attach(); + cmos_address = bios_get_cmos_address(); + + if (have_wifi) { + u16 wifi = bios_get_default_setting(WIFI); + if (wifi & 1) + wifi_enabled = (wifi & 2) ? 1 : 0; + else + have_wifi = 0; + + if (have_wifi) + bios_set_state(WIFI, wifi_enabled); + } + + if (have_bluetooth) { + u16 bt = bios_get_default_setting(BLUETOOTH); + if (bt & 1) + bluetooth_enabled = (bt & 2) ? 1 : 0; + else + have_bluetooth = 0; + + if (have_bluetooth) + bios_set_state(BLUETOOTH, bluetooth_enabled); + } + + poll_bios(1); /* Flush stale event queue and arm timer */ + + return 0; +} + +static int __devexit wistron_remove(struct platform_device *dev) +{ + del_timer_sync(&poll_timer); + input_unregister_device(input_dev); + bios_detach(); + + return 0; +} + +#ifdef CONFIG_PM static int wistron_suspend(struct platform_device *dev, pm_message_t state) { del_timer_sync(&poll_timer); @@ -472,13 +537,20 @@ static int wistron_resume(struct platform_device *dev) return 0; } +#else +#define wistron_suspend NULL +#define wistron_resume NULL +#endif static struct platform_driver wistron_driver = { - .suspend = wistron_suspend, - .resume = wistron_resume, .driver = { .name = "wistron-bios", + .owner = THIS_MODULE, }, + .probe = wistron_probe, + .remove = __devexit_p(wistron_remove), + .suspend = wistron_suspend, + .resume = wistron_resume, }; static int __init wb_module_init(void) @@ -493,55 +565,27 @@ static int __init wb_module_init(void) if (err) return err; - bios_attach(); - cmos_address = bios_get_cmos_address(); - err = platform_driver_register(&wistron_driver); if (err) - goto err_detach_bios; + goto err_unmap_bios; - wistron_device = platform_device_register_simple("wistron-bios", -1, NULL, 0); - if (IS_ERR(wistron_device)) { - err = PTR_ERR(wistron_device); + wistron_device = platform_device_alloc("wistron-bios", -1); + if (!wistron_device) { + err = -ENOMEM; goto err_unregister_driver; } - if (have_wifi) { - u16 wifi = bios_get_default_setting(WIFI); - if (wifi & 1) - wifi_enabled = (wifi & 2) ? 1 : 0; - else - have_wifi = 0; - - if (have_wifi) - bios_set_state(WIFI, wifi_enabled); - } - - if (have_bluetooth) { - u16 bt = bios_get_default_setting(BLUETOOTH); - if (bt & 1) - bluetooth_enabled = (bt & 2) ? 1 : 0; - else - have_bluetooth = 0; - - if (have_bluetooth) - bios_set_state(BLUETOOTH, bluetooth_enabled); - } - - err = setup_input_dev(); + err = platform_device_add(wistron_device); if (err) - goto err_unregister_device; - - poll_bios(1); /* Flush stale event queue and arm timer */ + goto err_free_device; return 0; - err_unregister_device: - platform_device_unregister(wistron_device); + err_free_device: + platform_device_put(wistron_device); err_unregister_driver: platform_driver_unregister(&wistron_driver); - err_detach_bios: - bios_detach(); + err_unmap_bios: unmap_bios(); return err; @@ -549,11 +593,8 @@ static int __init wb_module_init(void) static void __exit wb_module_exit(void) { - del_timer_sync(&poll_timer); - input_unregister_device(input_dev); platform_device_unregister(wistron_device); platform_driver_unregister(&wistron_driver); - bios_detach(); unmap_bios(); } diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 4f41ec3e4332..24474335dfd1 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -40,6 +40,7 @@ static struct alps_model_info alps_model_data[] = { { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, + { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */ { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 55991424ac91..5ccc3ef3b89e 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -27,6 +27,13 @@ static struct dmi_system_id lifebook_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), }, }, + { + .ident = "Lifebook B142", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), + }, + + }, { } }; diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 31a59f7abfaf..025a71de5404 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -226,7 +226,9 @@ static struct ps2pp_info *get_model_info(unsigned char model) { 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, { 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, + { 85, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, + { 87, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 96, 0, 0 }, { 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL }, diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 6ee9999a2eaa..4d5ecc04c5b6 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -527,11 +527,15 @@ static int psmouse_extensions(struct psmouse *psmouse, if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0) return PSMOUSE_PS2PP; + if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0) + return PSMOUSE_TRACKPOINT; + /* * Reset to defaults in case the device got confused by extended - * protocol probes. + * protocol probes. Note that we do full reset becuase some mice + * put themselves to sleep when see PSMOUSE_RESET_DIS. */ - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); + psmouse_reset(psmouse); if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0) return PSMOUSE_IMEX; @@ -540,12 +544,6 @@ static int psmouse_extensions(struct psmouse *psmouse, return PSMOUSE_IMPS; /* - * Try to initialize the IBM TrackPoint - */ - if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0) - return PSMOUSE_TRACKPOINT; - -/* * Okay, all failed, we have a standard mouse here. The number of the buttons * is still a question, though. We assume 3. */ @@ -559,7 +557,6 @@ static int psmouse_extensions(struct psmouse *psmouse, * extensions. */ psmouse_reset(psmouse); - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); } return PSMOUSE_PS2; diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 2d0af44ac4b9..81fd7a97a93d 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -40,15 +40,15 @@ MODULE_LICENSE("GPL"); #endif static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X; -module_param(xres, uint, 0); +module_param(xres, uint, 0644); MODULE_PARM_DESC(xres, "Horizontal screen resolution"); static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y; -module_param(yres, uint, 0); +module_param(yres, uint, 0644); MODULE_PARM_DESC(yres, "Vertical screen resolution"); static unsigned tap_time = 200; -module_param(tap_time, uint, 0); +module_param(tap_time, uint, 0644); MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)"); struct mousedev_hw_data { @@ -155,7 +155,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, switch (code) { case ABS_X: size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; - if (size == 0) size = xres; + if (size == 0) size = xres ? : 1; if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X]; if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X]; mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size; @@ -164,7 +164,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, case ABS_Y: size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; - if (size == 0) size = yres; + if (size == 0) size = yres ? : 1; if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y]; if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y]; mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size; diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c index 4da6c86b5d76..096b6a0b5cca 100644 --- a/drivers/input/serio/ct82c710.c +++ b/drivers/input/serio/ct82c710.c @@ -154,7 +154,7 @@ static int ct82c710_write(struct serio *port, unsigned char c) * See if we can find a 82C710 device. Read mouse address. */ -static int __init ct82c710_probe(void) +static int __init ct82c710_detect(void) { outb_p(0x55, 0x2fa); /* Any value except 9, ff or 36 */ outb_p(0xaa, 0x3fa); /* Inverse of 55 */ @@ -163,7 +163,7 @@ static int __init ct82c710_probe(void) outb_p(0x1b, 0x2fa); /* Inverse of e4 */ outb_p(0x0f, 0x390); /* Write index */ if (inb_p(0x391) != 0xe4) /* Config address found? */ - return -1; /* No: no 82C710 here */ + return -ENODEV; /* No: no 82C710 here */ outb_p(0x0d, 0x390); /* Write index */ ct82c710_iores.start = inb_p(0x391) << 2; /* Get mouse I/O address */ @@ -175,51 +175,88 @@ static int __init ct82c710_probe(void) return 0; } -static struct serio * __init ct82c710_allocate_port(void) +static int __devinit ct82c710_probe(struct platform_device *dev) { - struct serio *serio; - - serio = kmalloc(sizeof(struct serio), GFP_KERNEL); - if (serio) { - memset(serio, 0, sizeof(struct serio)); - serio->id.type = SERIO_8042; - serio->open = ct82c710_open; - serio->close = ct82c710_close; - serio->write = ct82c710_write; - serio->dev.parent = &ct82c710_device->dev; - strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name)); - snprintf(serio->phys, sizeof(serio->phys), "isa%04lx/serio0", CT82C710_DATA); - } + ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL); + if (!ct82c710_port) + return -ENOMEM; + + ct82c710_port->id.type = SERIO_8042; + ct82c710_port->dev.parent = &dev->dev; + ct82c710_port->open = ct82c710_open; + ct82c710_port->close = ct82c710_close; + ct82c710_port->write = ct82c710_write; + strlcpy(ct82c710_port->name, "C&T 82c710 mouse port", + sizeof(ct82c710_port->name)); + snprintf(ct82c710_port->phys, sizeof(ct82c710_port->phys), + "isa%04lx/serio0", CT82C710_DATA); + + serio_register_port(ct82c710_port); + + return 0; +} + +static int __devexit ct82c710_remove(struct platform_device *dev) +{ + serio_unregister_port(ct82c710_port); - return serio; + return 0; } +static struct platform_driver ct82c710_driver = { + .driver = { + .name = "ct82c710", + .owner = THIS_MODULE, + }, + .probe = ct82c710_probe, + .remove = __devexit_p(ct82c710_remove), +}; + + static int __init ct82c710_init(void) { - if (ct82c710_probe()) - return -ENODEV; + int error; - ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1); - if (IS_ERR(ct82c710_device)) - return PTR_ERR(ct82c710_device); + error = ct82c710_detect(); + if (error) + return error; - if (!(ct82c710_port = ct82c710_allocate_port())) { - platform_device_unregister(ct82c710_device); - return -ENOMEM; + error = platform_driver_register(&ct82c710_driver); + if (error) + return error; + + ct82c710_device = platform_device_alloc("ct82c710", -1); + if (!ct82c710_device) { + error = -ENOMEM; + goto err_unregister_driver; } + error = platform_device_add_resources(ct82c710_device, &ct82c710_iores, 1); + if (error) + goto err_free_device; + + error = platform_device_add(ct82c710_device); + if (error) + goto err_free_device; + serio_register_port(ct82c710_port); printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n", CT82C710_DATA, CT82C710_IRQ); return 0; + + err_free_device: + platform_device_put(ct82c710_device); + err_unregister_driver: + platform_driver_unregister(&ct82c710_driver); + return error; } static void __exit ct82c710_exit(void) { - serio_unregister_port(ct82c710_port); platform_device_unregister(ct82c710_device); + platform_driver_unregister(&ct82c710_driver); } module_init(ct82c710_init); diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 273bb3b08cfa..057beca1986a 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -158,6 +158,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"), }, }, + { + .ident = "Sharp Actius MM20", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SHARP"), + DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), + }, + }, { } }; diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index ac86c1d1d83e..a7d91d5356a5 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -572,7 +572,7 @@ static int i8042_enable_mux_ports(void) * LCS/Telegraphics. */ -static int __init i8042_check_mux(void) +static int __devinit i8042_check_mux(void) { unsigned char mux_version; @@ -600,7 +600,7 @@ static int __init i8042_check_mux(void) * the presence of an AUX interface. */ -static int __init i8042_check_aux(void) +static int __devinit i8042_check_aux(void) { unsigned char param; static int i8042_check_aux_cookie; @@ -678,7 +678,7 @@ static int __init i8042_check_aux(void) * registers it, and reports to the user. */ -static int __init i8042_port_register(struct i8042_port *port) +static int __devinit i8042_port_register(struct i8042_port *port) { i8042_ctr &= ~port->disable; @@ -956,7 +956,6 @@ static int i8042_resume(struct platform_device *dev) panic_blink = i8042_panic_blink; return 0; - } /* @@ -969,16 +968,7 @@ static void i8042_shutdown(struct platform_device *dev) i8042_controller_cleanup(); } -static struct platform_driver i8042_driver = { - .suspend = i8042_suspend, - .resume = i8042_resume, - .shutdown = i8042_shutdown, - .driver = { - .name = "i8042", - }, -}; - -static int __init i8042_create_kbd_port(void) +static int __devinit i8042_create_kbd_port(void) { struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; @@ -1003,7 +993,7 @@ static int __init i8042_create_kbd_port(void) return i8042_port_register(port); } -static int __init i8042_create_aux_port(void) +static int __devinit i8042_create_aux_port(void) { struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; @@ -1028,7 +1018,7 @@ static int __init i8042_create_aux_port(void) return i8042_port_register(port); } -static int __init i8042_create_mux_port(int index) +static int __devinit i8042_create_mux_port(int index) { struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; @@ -1057,37 +1047,16 @@ static int __init i8042_create_mux_port(int index) return i8042_port_register(port); } -static int __init i8042_init(void) +static int __devinit i8042_probe(struct platform_device *dev) { int i, have_ports = 0; int err; - dbg_init(); - init_timer(&i8042_timer); i8042_timer.function = i8042_timer_func; - err = i8042_platform_init(); - if (err) - return err; - - i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ; - i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; - - if (i8042_controller_init()) { - err = -ENODEV; - goto err_platform_exit; - } - - err = platform_driver_register(&i8042_driver); - if (err) - goto err_controller_cleanup; - - i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0); - if (IS_ERR(i8042_platform_device)) { - err = PTR_ERR(i8042_platform_device); - goto err_unregister_driver; - } + if (i8042_controller_init()) + return -ENODEV; if (!i8042_noaux && !i8042_check_aux()) { if (!i8042_nomux && !i8042_check_mux()) { @@ -1113,30 +1082,23 @@ static int __init i8042_init(void) if (!have_ports) { err = -ENODEV; - goto err_unregister_device; + goto err_controller_cleanup; } mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); - return 0; err_unregister_ports: for (i = 0; i < I8042_NUM_PORTS; i++) if (i8042_ports[i].serio) serio_unregister_port(i8042_ports[i].serio); - err_unregister_device: - platform_device_unregister(i8042_platform_device); - err_unregister_driver: - platform_driver_unregister(&i8042_driver); err_controller_cleanup: i8042_controller_cleanup(); - err_platform_exit: - i8042_platform_exit(); return err; } -static void __exit i8042_exit(void) +static int __devexit i8042_remove(struct platform_device *dev) { int i; @@ -1148,6 +1110,62 @@ static void __exit i8042_exit(void) del_timer_sync(&i8042_timer); + return 0; +} + +static struct platform_driver i8042_driver = { + .driver = { + .name = "i8042", + .owner = THIS_MODULE, + }, + .probe = i8042_probe, + .remove = __devexit_p(i8042_remove), + .suspend = i8042_suspend, + .resume = i8042_resume, + .shutdown = i8042_shutdown, +}; + +static int __init i8042_init(void) +{ + int err; + + dbg_init(); + + err = i8042_platform_init(); + if (err) + return err; + + i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ; + i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; + + err = platform_driver_register(&i8042_driver); + if (err) + goto err_platform_exit; + + i8042_platform_device = platform_device_alloc("i8042", -1); + if (!i8042_platform_device) { + err = -ENOMEM; + goto err_unregister_driver; + } + + err = platform_device_add(i8042_platform_device); + if (err) + goto err_free_device; + + return 0; + + err_free_device: + platform_device_put(i8042_platform_device); + err_unregister_driver: + platform_driver_unregister(&i8042_driver); + err_platform_exit: + i8042_platform_exit(); + + return err; +} + +static void __exit i8042_exit(void) +{ platform_device_unregister(i8042_platform_device); platform_driver_unregister(&i8042_driver); diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c index d857f7081adb..f08a5d0cd5fa 100644 --- a/drivers/input/serio/maceps2.c +++ b/drivers/input/serio/maceps2.c @@ -118,13 +118,12 @@ static void maceps2_close(struct serio *dev) } -static struct serio * __init maceps2_allocate_port(int idx) +static struct serio * __devinit maceps2_allocate_port(int idx) { struct serio *serio; - serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(struct serio), GFP_KERNEL); if (serio) { - memset(serio, 0, sizeof(struct serio)); serio->id.type = SERIO_8042; serio->write = maceps2_write; serio->open = maceps2_open; @@ -138,24 +137,13 @@ static struct serio * __init maceps2_allocate_port(int idx) return serio; } - -static int __init maceps2_init(void) +static int __devinit maceps2_probe(struct platform_device *dev) { - maceps2_device = platform_device_register_simple("maceps2", -1, NULL, 0); - if (IS_ERR(maceps2_device)) - return PTR_ERR(maceps2_device); - - port_data[0].port = &mace->perif.ps2.keyb; - port_data[0].irq = MACEISA_KEYB_IRQ; - port_data[1].port = &mace->perif.ps2.mouse; - port_data[1].irq = MACEISA_MOUSE_IRQ; - maceps2_port[0] = maceps2_allocate_port(0); maceps2_port[1] = maceps2_allocate_port(1); if (!maceps2_port[0] || !maceps2_port[1]) { kfree(maceps2_port[0]); kfree(maceps2_port[1]); - platform_device_unregister(maceps2_device); return -ENOMEM; } @@ -165,11 +153,59 @@ static int __init maceps2_init(void) return 0; } -static void __exit maceps2_exit(void) +static int __devexit maceps2_remove(struct platform_device *dev) { serio_unregister_port(maceps2_port[0]); serio_unregister_port(maceps2_port[1]); + + return 0; +} + +static struct platform_driver maceps2_driver = { + .driver = { + .name = "maceps2", + .owner = THIS_MODULE, + }, + .probe = maceps2_probe, + .remove = __devexit_p(maceps2_remove), +}; + +static int __init maceps2_init(void) +{ + int error; + + error = platform_driver_register(&maceps2_driver); + if (error) + return error; + + maceps2_device = platform_device_alloc("maceps2", -1); + if (!maceps2_device) { + error = -ENOMEM; + goto err_unregister_driver; + } + + port_data[0].port = &mace->perif.ps2.keyb; + port_data[0].irq = MACEISA_KEYB_IRQ; + port_data[1].port = &mace->perif.ps2.mouse; + port_data[1].irq = MACEISA_MOUSE_IRQ; + + error = platform_device_add(maceps2_device); + if (error) + goto err_free_device; + + return 0; + + err_free_device: + platform_device_put(maceps2_device); + err_unregister_driver: + platform_driver_unregister(&maceps2_driver); + return error; +} + +static void __exit maceps2_exit(void) +{ platform_device_unregister(maceps2_device); + platform_driver_unregister(&maceps2_driver); } module_init(maceps2_init); diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index b44d255596c2..d3827c5fe119 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c @@ -75,13 +75,13 @@ static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void q40kbd_flush(void) { - int maxread = 100; + int maxread = 100; unsigned long flags; spin_lock_irqsave(&q40kbd_lock, flags); - while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))) - master_inb(KEYCODE_REG); + while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))) + master_inb(KEYCODE_REG); spin_unlock_irqrestore(&q40kbd_lock, flags); } @@ -97,14 +97,14 @@ static int q40kbd_open(struct serio *port) if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) { printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD); - return -1; + return -EBUSY; } - /* off we go */ - master_outb(-1, KEYBOARD_UNLOCK_REG); - master_outb(1, KEY_IRQ_ENABLE_REG); + /* off we go */ + master_outb(-1, KEYBOARD_UNLOCK_REG); + master_outb(1, KEY_IRQ_ENABLE_REG); - return 0; + return 0; } static void q40kbd_close(struct serio *port) @@ -116,48 +116,73 @@ static void q40kbd_close(struct serio *port) q40kbd_flush(); } -static struct serio * __init q40kbd_allocate_port(void) +static int __devinit q40kbd_probe(struct platform_device *dev) { - struct serio *serio; - - serio = kmalloc(sizeof(struct serio), GFP_KERNEL); - if (serio) { - memset(serio, 0, sizeof(struct serio)); - serio->id.type = SERIO_8042; - serio->open = q40kbd_open; - serio->close = q40kbd_close; - serio->dev.parent = &q40kbd_device->dev; - strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name)); - strlcpy(serio->phys, "Q40", sizeof(serio->phys)); - } + q40kbd_port = kzalloc(sizeof(struct serio), GFP_KERNEL); + if (!q40kbd_port) + return -ENOMEM; + + q40kbd_port->id.type = SERIO_8042; + q40kbd_port->open = q40kbd_open; + q40kbd_port->close = q40kbd_close; + q40kbd_port->dev.parent = &dev->dev; + strlcpy(q40kbd_port->name, "Q40 Kbd Port", sizeof(q40kbd_port->name)); + strlcpy(q40kbd_port->phys, "Q40", sizeof(q40kbd_port->phys)); + + serio_register_port(q40kbd_port); + printk(KERN_INFO "serio: Q40 kbd registered\n"); - return serio; + return 0; } +static int __devexit q40kbd_remove(struct platform_device *dev) +{ + serio_unregister_port(q40kbd_port); + + return 0; +} + +static struct platform_driver q40kbd_driver = { + .driver = { + .name = "q40kbd", + .owner = THIS_MODULE, + }, + .probe = q40kbd_probe, + .remove = __devexit_p(q40kbd_remove), +}; + static int __init q40kbd_init(void) { + int error; + if (!MACH_IS_Q40) return -EIO; - q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0); - if (IS_ERR(q40kbd_device)) - return PTR_ERR(q40kbd_device); + error = platform_driver_register(&q40kbd_driver); + if (error) + return error; - if (!(q40kbd_port = q40kbd_allocate_port())) { - platform_device_unregister(q40kbd_device); - return -ENOMEM; - } + q40kbd_device = platform_device_alloc("q40kbd", -1); + if (!q40kbd_device) + goto err_unregister_driver; - serio_register_port(q40kbd_port); - printk(KERN_INFO "serio: Q40 kbd registered\n"); + error = platform_device_add(q40kbd_device); + if (error) + goto err_free_device; return 0; + + err_free_device: + platform_device_put(q40kbd_device); + err_unregister_driver: + platform_driver_unregister(&q40kbd_driver); + return error; } static void __exit q40kbd_exit(void) { - serio_unregister_port(q40kbd_port); platform_device_unregister(q40kbd_device); + platform_driver_unregister(&q40kbd_driver); } module_init(q40kbd_init); diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index 1949b54f41f2..c222ed13deab 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c @@ -6,6 +6,7 @@ * Copyright (C) 2005 Stelian Pop (stelian@popies.net) * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) + * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) * * Thanks to Alex Harper <basilisk@foobox.net> for his inputs. * @@ -38,6 +39,11 @@ /* Apple has powerbooks which have the keyboard with different Product IDs */ #define APPLE_VENDOR_ID 0x05AC +/* These names come from Info.plist in AppleUSBTrackpad.kext */ +#define GEYSER_ANSI_PRODUCT_ID 0x0214 +#define GEYSER_ISO_PRODUCT_ID 0x0215 +#define GEYSER_JIS_PRODUCT_ID 0x0216 + #define ATP_DEVICE(prod) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ USB_DEVICE_ID_MATCH_INT_CLASS | \ @@ -53,13 +59,17 @@ static struct usb_device_id atp_table [] = { { ATP_DEVICE(0x020F) }, { ATP_DEVICE(0x030A) }, { ATP_DEVICE(0x030B) }, - { } /* Terminating entry */ + + /* PowerBooks Oct 2005 */ + { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, + + /* Terminating entry */ + { } }; MODULE_DEVICE_TABLE (usb, atp_table); -/* size of a USB urb transfer */ -#define ATP_DATASIZE 81 - /* * number of sensors. Note that only 16 instead of 26 X (horizontal) * sensors exist on 12" and 15" PowerBooks. All models have 16 Y @@ -108,6 +118,8 @@ struct atp { signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; /* accumulated sensors */ int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; + int overflowwarn; /* overflow warning printed? */ + int datalen; /* size of an USB urb transfer */ }; #define dbg_dump(msg, tab) \ @@ -124,7 +136,7 @@ struct atp { if (debug) printk(format, ##a); \ } while (0) -MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold"); +MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann"); MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver"); MODULE_LICENSE("GPL"); @@ -132,6 +144,16 @@ static int debug = 1; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activate debugging output"); +/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ +static inline int atp_is_geyser_2(struct atp *dev) +{ + int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct); + + return (productId == GEYSER_ANSI_PRODUCT_ID) || + (productId == GEYSER_ISO_PRODUCT_ID) || + (productId == GEYSER_JIS_PRODUCT_ID); +} + static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, int *z, int *fingers) { @@ -168,13 +190,20 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers) static void atp_complete(struct urb* urb, struct pt_regs* regs) { int x, y, x_z, y_z, x_f, y_f; - int retval, i; + int retval, i, j; struct atp *dev = urb->context; switch (urb->status) { case 0: /* success */ break; + case -EOVERFLOW: + if(!dev->overflowwarn) { + printk("appletouch: OVERFLOW with data " + "length %d, actual length is %d\n", + dev->datalen, dev->urb->actual_length); + dev->overflowwarn = 1; + } case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: @@ -189,23 +218,45 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) } /* drop incomplete datasets */ - if (dev->urb->actual_length != ATP_DATASIZE) { + if (dev->urb->actual_length != dev->datalen) { dprintk("appletouch: incomplete data package.\n"); goto exit; } /* reorder the sensors values */ - for (i = 0; i < 8; i++) { - /* X values */ - dev->xy_cur[i ] = dev->data[5 * i + 2]; - dev->xy_cur[i + 8] = dev->data[5 * i + 4]; - dev->xy_cur[i + 16] = dev->data[5 * i + 42]; - if (i < 2) - dev->xy_cur[i + 24] = dev->data[5 * i + 44]; - - /* Y values */ - dev->xy_cur[i + 26] = dev->data[5 * i + 1]; - dev->xy_cur[i + 34] = dev->data[5 * i + 3]; + if (atp_is_geyser_2(dev)) { + memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); + + /* + * The values are laid out like this: + * Y1, Y2, -, Y3, Y4, -, ..., X1, X2, -, X3, X4, -, ... + * '-' is an unused value. + */ + + /* read X values */ + for (i = 0, j = 19; i < 20; i += 2, j += 3) { + dev->xy_cur[i] = dev->data[j]; + dev->xy_cur[i + 1] = dev->data[j + 1]; + } + + /* read Y values */ + for (i = 0, j = 1; i < 9; i += 2, j += 3) { + dev->xy_cur[ATP_XSENSORS + i] = dev->data[j]; + dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 1]; + } + } else { + for (i = 0; i < 8; i++) { + /* X values */ + dev->xy_cur[i ] = dev->data[5 * i + 2]; + dev->xy_cur[i + 8] = dev->data[5 * i + 4]; + dev->xy_cur[i + 16] = dev->data[5 * i + 42]; + if (i < 2) + dev->xy_cur[i + 24] = dev->data[5 * i + 44]; + + /* Y values */ + dev->xy_cur[i + 26] = dev->data[5 * i + 1]; + dev->xy_cur[i + 34] = dev->data[5 * i + 3]; + } } dbg_dump("sample", dev->xy_cur); @@ -216,16 +267,24 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) dev->x_old = dev->y_old = -1; memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); - /* 17" Powerbooks have 10 extra X sensors */ - for (i = 16; i < ATP_XSENSORS; i++) - if (dev->xy_cur[i]) { - printk("appletouch: 17\" model detected.\n"); + /* 17" Powerbooks have extra X sensors */ + for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { + if (!dev->xy_cur[i]) continue; + + printk("appletouch: 17\" model detected.\n"); + if(atp_is_geyser_2(dev)) + input_set_abs_params(dev->input, ABS_X, 0, + (20 - 1) * + ATP_XFACT - 1, + ATP_FUZZ, 0); + else input_set_abs_params(dev->input, ABS_X, 0, (ATP_XSENSORS - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); - break; - } + + break; + } goto exit; } @@ -282,7 +341,8 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); } - input_report_key(dev->input, BTN_LEFT, !!dev->data[80]); + input_report_key(dev->input, BTN_LEFT, + !!dev->data[dev->datalen - 1]); input_sync(dev->input); @@ -353,6 +413,8 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id dev->udev = udev; dev->input = input_dev; + dev->overflowwarn = 0; + dev->datalen = (atp_is_geyser_2(dev)?64:81); dev->urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->urb) { @@ -360,7 +422,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id goto err_free_devs; } - dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL, + dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL, &dev->urb->transfer_dma); if (!dev->data) { retval = -ENOMEM; @@ -369,7 +431,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id usb_fill_int_urb(dev->urb, udev, usb_rcvintpipe(udev, int_in_endpointAddr), - dev->data, ATP_DATASIZE, atp_complete, dev, 1); + dev->data, dev->datalen, atp_complete, dev, 1); usb_make_path(udev, dev->phys, sizeof(dev->phys)); strlcat(dev->phys, "/input0", sizeof(dev->phys)); @@ -385,14 +447,25 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id set_bit(EV_ABS, input_dev->evbit); - /* - * 12" and 15" Powerbooks only have 16 x sensors, - * 17" models are detected later. - */ - input_set_abs_params(input_dev, ABS_X, 0, - (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); - input_set_abs_params(input_dev, ABS_Y, 0, - (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0); + if (atp_is_geyser_2(dev)) { + /* + * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected + * later. + */ + input_set_abs_params(input_dev, ABS_X, 0, + ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0); + input_set_abs_params(input_dev, ABS_Y, 0, + ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0); + } else { + /* + * 12" and 15" Powerbooks only have 16 x sensors, + * 17" models are detected later. + */ + input_set_abs_params(input_dev, ABS_X, 0, + (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); + input_set_abs_params(input_dev, ABS_Y, 0, + (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0); + } input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); set_bit(EV_KEY, input_dev->evbit); @@ -427,7 +500,7 @@ static void atp_disconnect(struct usb_interface *iface) usb_kill_urb(dev->urb); input_unregister_device(dev->input); usb_free_urb(dev->urb); - usb_buffer_free(dev->udev, ATP_DATASIZE, + usb_buffer_free(dev->udev, dev->datalen, dev->data, dev->urb->transfer_dma); kfree(dev); } diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h index ceebab99eff2..4a42162ee2ea 100644 --- a/drivers/usb/input/hid-debug.h +++ b/drivers/usb/input/hid-debug.h @@ -681,6 +681,7 @@ static char *keys[KEY_MAX + 1] = { [KEY_SEND] = "Send", [KEY_REPLY] = "Reply", [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save", [KEY_DOCUMENTS] = "Documents", + [KEY_FN] = "Fn", }; static char *relatives[REL_MAX + 1] = { |