]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
authorDmitry Torokhov <dtor_core@ameritech.net>
Fri, 6 Jan 2006 03:25:13 +0000 (22:25 -0500)
committerDmitry Torokhov <dtor_core@ameritech.net>
Fri, 6 Jan 2006 03:25:13 +0000 (22:25 -0500)
19 files changed:
Documentation/input/appletouch.txt
drivers/input/evdev.c
drivers/input/gameport/Kconfig
drivers/input/misc/m68kspkr.c
drivers/input/misc/pcspkr.c
drivers/input/misc/sparcspkr.c
drivers/input/misc/wistron_btns.c
drivers/input/mouse/alps.c
drivers/input/mouse/lifebook.c
drivers/input/mouse/logips2pp.c
drivers/input/mouse/psmouse-base.c
drivers/input/mousedev.c
drivers/input/serio/ct82c710.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042.c
drivers/input/serio/maceps2.c
drivers/input/serio/q40kbd.c
drivers/usb/input/appletouch.c
drivers/usb/input/hid-debug.h

index b48d11d0326d1b530a6f083e4467c9c108a97d15..4f7c633a76d2877a0f11a87dd88add524106c67b 100644 (file)
@@ -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:
 ------
index 9f2352bd8348efa34047125a4f72c181dd5d9f93..0270d1ec9425b27a329774a3eb9625a5c808c760 100644 (file)
@@ -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
 
index 7524bd7d8b8f7c602db8c16b649333b0b53cd7d4..d279454a5c9e1f72111f62b21363eaa1bb2bbc2e 100644 (file)
@@ -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
index 04489ad7702a21c9c31baed48bc963a695217cc9..8d6c3837badb78a51f89f585d464d3cbdf043f84 100644 (file)
@@ -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);
index 68ac97f101b0369a6f7a358829a3d6fd25dc4910..1ef477f4469c1a1e359bd4cbacc7917680c95524 100644 (file)
@@ -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);
index 29d97b12be7a4bc1753e7279e774b7e007fe7b6f..f0fd2c4740f19611678a927a6302a0fc4e27cced 100644 (file)
@@ -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);
index bac3085185fe6d3c38c48d28793262de9bea7ddb..a05b8557842f56554ceb88bb4edbbfb2c44305fe 100644 (file)
@@ -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(&regs);
 }
 
-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();
 }
 
index 4f41ec3e4332162fc9187a5c2ef4d7e0ac017ff0..24474335dfd1f38fb171817b844e3c8ec6a24771 100644 (file)
@@ -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 */
index 55991424ac914e306730b01def48006e69db0f6d..5ccc3ef3b89e84fe4d246a7a3fc6fd6d0b943394 100644 (file)
@@ -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"),
+               },
+
+       },
        { }
 };
 
index 31a59f7abfaf616b6cc985d03958aaf553e95e5d..025a71de540415ce58ca3be10c94b0ae80ac66e3 100644 (file)
@@ -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 },
index 6ee9999a2eaa3fdfb8a87812d625c67ef4373fa9..4d5ecc04c5b65382d5b8de27c345e2ba8813e05e 100644 (file)
@@ -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;
@@ -539,12 +543,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
        if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse, set_properties) == 0)
                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;
index 2d0af44ac4b9650871972e6af74cf4ff2771a2b0..81fd7a97a93df5e08574edd6b3551728e626225f 100644 (file)
@@ -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;
index 4da6c86b5d76a46979104b2dcc87edadd0cde7e8..096b6a0b5ccad6598702233350322d71f28860a6 100644 (file)
@@ -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);
index 273bb3b08cfa254146cf1b6362bfc8b1df1e224e..057beca1986a29887d2a0e330a4e86bd6921ed8c 100644 (file)
@@ -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"),
+               },
+       },
        { }
 };
 
index ac86c1d1d83e4a24bffdc6bcaa94ab66cffc75c9..a7d91d5356a55c67035cf8ab5c0b183a1fffa05a 100644 (file)
@@ -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);
 
index d857f7081adb03e408778dc0f7ce058e79df08e3..f08a5d0cd5fae5c148a8bd697e6c93af213db3ba 100644 (file)
@@ -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);
index b44d255596c25db08eb1c184c29f4f4468e08f14..d3827c5fe119735834e161493749619936e63582 100644 (file)
@@ -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);
index 1949b54f41f2500abfdd24372fb5ea19e37df0f7..c222ed13deab49de122ee3a57851a33045f58ef9 100644 (file)
@@ -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.
  *
 /* 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);
        }
index ceebab99eff24e08017efb8e7acf80826aab7d74..4a42162ee2ea9560ccfc8f5ba8ebb7388d2d6ca9 100644 (file)
@@ -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] = {