Loading Documentation/input/appletouch.txt +3 −2 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -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: ------ Loading drivers/input/evdev.c +213 −280 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -165,22 +166,80 @@ 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 int evdev_event_to_user(char __user *buffer, const struct input_event *event) { if (COMPAT_TEST) { struct input_event_compat compat_event; 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; if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat))) return -EFAULT; } else { if (copy_to_user(buffer, event, sizeof(struct input_event))) return -EFAULT; } return 0; } #else static inline size_t evdev_event_size(void) { return sizeof(struct input_event); } 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; return 0; } 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; return 0; } #endif /* CONFIG_COMPAT */ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) { Loading @@ -188,31 +247,26 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ struct input_event event; int retval = 0; if (!list->evdev->exist) return -ENODEV; #ifdef CONFIG_COMPAT if (COMPAT_TEST) return evdev_write_compat(file, buffer, count, ppos); #endif if (!list->evdev->exist) return -ENODEV; while (retval < count) { if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) if (evdev_event_from_user(buffer + retval, &event)) return -EFAULT; input_event(list->evdev->handle.dev, event.type, event.code, event.value); retval += sizeof(struct input_event); retval += evdev_event_size(); } return retval; } #ifdef CONFIG_COMPAT static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos) 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; if (count < sizeof(struct input_event_compat)) if (count < evdev_event_size()) return -EINVAL; if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) Loading @@ -227,80 +281,118 @@ static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_ if (!list->evdev->exist) return -ENODEV; while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) { while (list->head != list->tail && retval + evdev_event_size() <= 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; if (evdev_event_to_user(buffer + retval, event)) return -EFAULT; list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); retval += sizeof(struct input_event_compat); retval += evdev_event_size(); } return retval; } #endif static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) /* No kernel lock - fine */ static unsigned int evdev_poll(struct file *file, poll_table *wait) { struct evdev_list *list = file->private_data; int retval; poll_wait(file, &list->evdev->wait, wait); return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) | (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); } #ifdef CONFIG_COMPAT if (COMPAT_TEST) return evdev_read_compat(file, buffer, count, ppos); #endif if (count < sizeof(struct input_event)) return -EINVAL; #define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) #define NBITS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1) if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) return -EAGAIN; #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; retval = wait_event_interruptible(list->evdev->wait, list->head != list->tail || (!list->evdev->exist)); if (copy_to_user(p, bits, len)) return -EFAULT; } if (retval) return retval; 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 (!list->evdev->exist) return -ENODEV; if (len > maxlen) len = maxlen; 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; list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); retval += sizeof(struct input_event); return copy_to_user(p, bits, len) ? -EFAULT : len; } #endif /* __BIG_ENDIAN */ return retval; #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; } /* No kernel lock - fine */ static unsigned int evdev_poll(struct file *file, poll_table *wait) #endif /* CONFIG_COMPAT */ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) { struct evdev_list *list = file->private_data; poll_wait(file, &list->evdev->wait, wait); return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) | (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); 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(struct file *file, unsigned int cmd, unsigned long arg) 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) { Loading @@ -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) set_bit(u, dev->keybit); return 0; case EVIOCSFF: Loading @@ -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)) Loading @@ -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)) Loading Loading @@ -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))) { Loading Loading @@ -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_compat(struct file *file, unsigned int cmd, unsigned long arg) static long evdev_ioctl(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; return evdev_ioctl_handler(file, cmd, (void __user *)arg, 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; #ifdef CONFIG_COMPAT static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) { return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); } #endif Loading drivers/input/gameport/Kconfig +7 −0 Original line number Diff line number Diff line Loading @@ -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 drivers/input/keyboard/atkbd.c +1 −1 Original line number Diff line number Diff line Loading @@ -321,7 +321,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, switch (code) { case ATKBD_RET_BAT: atkbd->enabled = 0; serio_rescan(atkbd->ps2dev.serio); serio_reconnect(atkbd->ps2dev.serio); goto out; case ATKBD_RET_EMUL0: atkbd->emul = 1; Loading drivers/input/misc/m68kspkr.c +85 −17 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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) { Loading @@ -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) { 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); Loading Loading
Documentation/input/appletouch.txt +3 −2 Original line number Diff line number Diff line Loading @@ -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: Loading @@ -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: ------ Loading
drivers/input/evdev.c +213 −280 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -165,22 +166,80 @@ 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 int evdev_event_to_user(char __user *buffer, const struct input_event *event) { if (COMPAT_TEST) { struct input_event_compat compat_event; 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; if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat))) return -EFAULT; } else { if (copy_to_user(buffer, event, sizeof(struct input_event))) return -EFAULT; } return 0; } #else static inline size_t evdev_event_size(void) { return sizeof(struct input_event); } 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; return 0; } 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; return 0; } #endif /* CONFIG_COMPAT */ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) { Loading @@ -188,31 +247,26 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ struct input_event event; int retval = 0; if (!list->evdev->exist) return -ENODEV; #ifdef CONFIG_COMPAT if (COMPAT_TEST) return evdev_write_compat(file, buffer, count, ppos); #endif if (!list->evdev->exist) return -ENODEV; while (retval < count) { if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) if (evdev_event_from_user(buffer + retval, &event)) return -EFAULT; input_event(list->evdev->handle.dev, event.type, event.code, event.value); retval += sizeof(struct input_event); retval += evdev_event_size(); } return retval; } #ifdef CONFIG_COMPAT static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos) 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; if (count < sizeof(struct input_event_compat)) if (count < evdev_event_size()) return -EINVAL; if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) Loading @@ -227,80 +281,118 @@ static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_ if (!list->evdev->exist) return -ENODEV; while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) { while (list->head != list->tail && retval + evdev_event_size() <= 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; if (evdev_event_to_user(buffer + retval, event)) return -EFAULT; list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); retval += sizeof(struct input_event_compat); retval += evdev_event_size(); } return retval; } #endif static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) /* No kernel lock - fine */ static unsigned int evdev_poll(struct file *file, poll_table *wait) { struct evdev_list *list = file->private_data; int retval; poll_wait(file, &list->evdev->wait, wait); return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) | (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); } #ifdef CONFIG_COMPAT if (COMPAT_TEST) return evdev_read_compat(file, buffer, count, ppos); #endif if (count < sizeof(struct input_event)) return -EINVAL; #define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) #define NBITS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1) if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) return -EAGAIN; #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; retval = wait_event_interruptible(list->evdev->wait, list->head != list->tail || (!list->evdev->exist)); if (copy_to_user(p, bits, len)) return -EFAULT; } if (retval) return retval; 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 (!list->evdev->exist) return -ENODEV; if (len > maxlen) len = maxlen; 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; list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); retval += sizeof(struct input_event); return copy_to_user(p, bits, len) ? -EFAULT : len; } #endif /* __BIG_ENDIAN */ return retval; #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; } /* No kernel lock - fine */ static unsigned int evdev_poll(struct file *file, poll_table *wait) #endif /* CONFIG_COMPAT */ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) { struct evdev_list *list = file->private_data; poll_wait(file, &list->evdev->wait, wait); return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) | (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); 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(struct file *file, unsigned int cmd, unsigned long arg) 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) { Loading @@ -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) set_bit(u, dev->keybit); return 0; case EVIOCSFF: Loading @@ -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)) Loading @@ -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)) Loading Loading @@ -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))) { Loading Loading @@ -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_compat(struct file *file, unsigned int cmd, unsigned long arg) static long evdev_ioctl(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; return evdev_ioctl_handler(file, cmd, (void __user *)arg, 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; #ifdef CONFIG_COMPAT static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) { return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); } #endif Loading
drivers/input/gameport/Kconfig +7 −0 Original line number Diff line number Diff line Loading @@ -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
drivers/input/keyboard/atkbd.c +1 −1 Original line number Diff line number Diff line Loading @@ -321,7 +321,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, switch (code) { case ATKBD_RET_BAT: atkbd->enabled = 0; serio_rescan(atkbd->ps2dev.serio); serio_reconnect(atkbd->ps2dev.serio); goto out; case ATKBD_RET_EMUL0: atkbd->emul = 1; Loading
drivers/input/misc/m68kspkr.c +85 −17 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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) { Loading @@ -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) { 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); Loading