Merge git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
This commit is contained in:
commit
b9abaa3fb7
|
@ -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:
|
||||
------
|
||||
|
|
|
@ -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,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)
|
||||
{
|
||||
|
@ -188,75 +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
|
||||
|
||||
while (retval < count) {
|
||||
|
||||
if (copy_from_user(&event, buffer + retval, 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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static ssize_t evdev_read_compat(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))
|
||||
return -EINVAL;
|
||||
|
||||
if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
|
||||
return -EAGAIN;
|
||||
|
||||
retval = wait_event_interruptible(list->evdev->wait,
|
||||
list->head != list->tail || (!list->evdev->exist));
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
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;
|
||||
while (retval < count) {
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#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)
|
||||
{
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 __init m68kspkr_init(void)
|
||||
static int __devinit m68kspkr_probe(struct platform_device *dev)
|
||||
{
|
||||
if (!mach_beep) {
|
||||
printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
struct input_dev *input_dev;
|
||||
int err;
|
||||
|
||||
m68kspkr_dev = input_allocate_device();
|
||||
if (!m68kspkr_dev)
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_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;
|
||||
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;
|
||||
|
||||
m68kspkr_dev->evbit[0] = BIT(EV_SND);
|
||||
m68kspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
|
||||
m68kspkr_dev->event = m68kspkr_event;
|
||||
input_dev->evbit[0] = BIT(EV_SND);
|
||||
input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
|
||||
input_dev->event = m68kspkr_event;
|
||||
|
||||
input_register_device(m68kspkr_dev);
|
||||
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;
|
||||
}
|
||||
|
||||
err = platform_driver_register(&m68kspkr_platform_driver);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
m68kspkr_platform_device = platform_device_alloc("m68kspkr", -1);
|
||||
if (!m68kspkr_platform_device) {
|
||||
err = -ENOMEM;
|
||||
goto err_unregister_driver;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -174,7 +174,7 @@ static u16 bios_pop_queue(void)
|
|||
return regs.eax;
|
||||
}
|
||||
|
||||
static void __init bios_attach(void)
|
||||
static void __devinit bios_attach(void)
|
||||
{
|
||||
struct regs regs;
|
||||
|
||||
|
@ -194,7 +194,7 @@ static void bios_detach(void)
|
|||
call_bios(®s);
|
||||
}
|
||||
|
||||
static u8 __init bios_get_cmos_address(void)
|
||||
static u8 __devinit bios_get_cmos_address(void)
|
||||
{
|
||||
struct regs regs;
|
||||
|
||||
|
@ -206,7 +206,7 @@ static u8 __init bios_get_cmos_address(void)
|
|||
return regs.ecx;
|
||||
}
|
||||
|
||||
static u16 __init bios_get_default_setting(u8 subsys)
|
||||
static u16 __devinit bios_get_default_setting(u8 subsys)
|
||||
{
|
||||
struct regs regs;
|
||||
|
||||
|
@ -296,6 +296,16 @@ static struct key_entry keymap_acer_aspire_1500[] = {
|
|||
{ KE_END, 0 }
|
||||
};
|
||||
|
||||
static struct key_entry keymap_acer_travelmate_240[] = {
|
||||
{ KE_KEY, 0x31, KEY_MAIL },
|
||||
{ KE_KEY, 0x36, KEY_WWW },
|
||||
{ KE_KEY, 0x11, KEY_PROG1 },
|
||||
{ KE_KEY, 0x12, KEY_PROG2 },
|
||||
{ KE_BLUETOOTH, 0x44, 0 },
|
||||
{ KE_WIFI, 0x30, 0 },
|
||||
{ KE_END, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* If your machine is not here (which is currently rather likely), please send
|
||||
* a list of buttons and their key codes (reported when loading this module
|
||||
|
@ -320,6 +330,15 @@ static struct dmi_system_id dmi_ids[] = {
|
|||
},
|
||||
.driver_data = keymap_acer_aspire_1500
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Acer TravelMate 240",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"),
|
||||
},
|
||||
.driver_data = keymap_acer_travelmate_240
|
||||
},
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
|
@ -348,7 +367,7 @@ static int __init select_keymap(void)
|
|||
|
||||
static struct input_dev *input_dev;
|
||||
|
||||
static int __init setup_input_dev(void)
|
||||
static int __devinit setup_input_dev(void)
|
||||
{
|
||||
const struct key_entry *key;
|
||||
int error;
|
||||
|
@ -447,6 +466,52 @@ static void poll_bios(unsigned long discard)
|
|||
mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
|
||||
}
|
||||
|
||||
static int __devinit wistron_probe(struct platform_device *dev)
|
||||
{
|
||||
int err = setup_input_dev();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
bios_attach();
|
||||
cmos_address = bios_get_cmos_address();
|
||||
|
||||
if (have_wifi) {
|
||||
u16 wifi = bios_get_default_setting(WIFI);
|
||||
if (wifi & 1)
|
||||
wifi_enabled = (wifi & 2) ? 1 : 0;
|
||||
else
|
||||
have_wifi = 0;
|
||||
|
||||
if (have_wifi)
|
||||
bios_set_state(WIFI, wifi_enabled);
|
||||
}
|
||||
|
||||
if (have_bluetooth) {
|
||||
u16 bt = bios_get_default_setting(BLUETOOTH);
|
||||
if (bt & 1)
|
||||
bluetooth_enabled = (bt & 2) ? 1 : 0;
|
||||
else
|
||||
have_bluetooth = 0;
|
||||
|
||||
if (have_bluetooth)
|
||||
bios_set_state(BLUETOOTH, bluetooth_enabled);
|
||||
}
|
||||
|
||||
poll_bios(1); /* Flush stale event queue and arm timer */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit wistron_remove(struct platform_device *dev)
|
||||
{
|
||||
del_timer_sync(&poll_timer);
|
||||
input_unregister_device(input_dev);
|
||||
bios_detach();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wistron_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
del_timer_sync(&poll_timer);
|
||||
|
@ -472,13 +537,20 @@ static int wistron_resume(struct platform_device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define wistron_suspend NULL
|
||||
#define wistron_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver wistron_driver = {
|
||||
.suspend = wistron_suspend,
|
||||
.resume = wistron_resume,
|
||||
.driver = {
|
||||
.name = "wistron-bios",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = wistron_probe,
|
||||
.remove = __devexit_p(wistron_remove),
|
||||
.suspend = wistron_suspend,
|
||||
.resume = wistron_resume,
|
||||
};
|
||||
|
||||
static int __init wb_module_init(void)
|
||||
|
@ -493,55 +565,27 @@ static int __init wb_module_init(void)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
bios_attach();
|
||||
cmos_address = bios_get_cmos_address();
|
||||
|
||||
err = platform_driver_register(&wistron_driver);
|
||||
if (err)
|
||||
goto err_detach_bios;
|
||||
goto err_unmap_bios;
|
||||
|
||||
wistron_device = platform_device_register_simple("wistron-bios", -1, NULL, 0);
|
||||
if (IS_ERR(wistron_device)) {
|
||||
err = PTR_ERR(wistron_device);
|
||||
wistron_device = platform_device_alloc("wistron-bios", -1);
|
||||
if (!wistron_device) {
|
||||
err = -ENOMEM;
|
||||
goto err_unregister_driver;
|
||||
}
|
||||
|
||||
if (have_wifi) {
|
||||
u16 wifi = bios_get_default_setting(WIFI);
|
||||
if (wifi & 1)
|
||||
wifi_enabled = (wifi & 2) ? 1 : 0;
|
||||
else
|
||||
have_wifi = 0;
|
||||
|
||||
if (have_wifi)
|
||||
bios_set_state(WIFI, wifi_enabled);
|
||||
}
|
||||
|
||||
if (have_bluetooth) {
|
||||
u16 bt = bios_get_default_setting(BLUETOOTH);
|
||||
if (bt & 1)
|
||||
bluetooth_enabled = (bt & 2) ? 1 : 0;
|
||||
else
|
||||
have_bluetooth = 0;
|
||||
|
||||
if (have_bluetooth)
|
||||
bios_set_state(BLUETOOTH, bluetooth_enabled);
|
||||
}
|
||||
|
||||
err = setup_input_dev();
|
||||
err = platform_device_add(wistron_device);
|
||||
if (err)
|
||||
goto err_unregister_device;
|
||||
|
||||
poll_bios(1); /* Flush stale event queue and arm timer */
|
||||
goto err_free_device;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_device:
|
||||
platform_device_unregister(wistron_device);
|
||||
err_free_device:
|
||||
platform_device_put(wistron_device);
|
||||
err_unregister_driver:
|
||||
platform_driver_unregister(&wistron_driver);
|
||||
err_detach_bios:
|
||||
bios_detach();
|
||||
err_unmap_bios:
|
||||
unmap_bios();
|
||||
|
||||
return err;
|
||||
|
@ -549,11 +593,8 @@ static int __init wb_module_init(void)
|
|||
|
||||
static void __exit wb_module_exit(void)
|
||||
{
|
||||
del_timer_sync(&poll_timer);
|
||||
input_unregister_device(input_dev);
|
||||
platform_device_unregister(wistron_device);
|
||||
platform_driver_unregister(&wistron_driver);
|
||||
bios_detach();
|
||||
unmap_bios();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"),
|
||||
},
|
||||
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
|
||||
if (!ct82c710_port)
|
||||
return -ENOMEM;
|
||||
|
||||
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->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);
|
||||
|
||||
return serio;
|
||||
serio_register_port(ct82c710_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit ct82c710_remove(struct platform_device *dev)
|
||||
{
|
||||
serio_unregister_port(ct82c710_port);
|
||||
|
||||
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);
|
||||
|
|
|
@ -84,6 +84,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "OQO Model 01",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "00"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -158,6 +166,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"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,37 +116,18 @@ 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));
|
||||
}
|
||||
|
||||
return serio;
|
||||
}
|
||||
|
||||
static int __init q40kbd_init(void)
|
||||
{
|
||||
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);
|
||||
|
||||
if (!(q40kbd_port = q40kbd_allocate_port())) {
|
||||
platform_device_unregister(q40kbd_device);
|
||||
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");
|
||||
|
@ -154,10 +135,54 @@ static int __init q40kbd_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __exit q40kbd_exit(void)
|
||||
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;
|
||||
|
||||
error = platform_driver_register(&q40kbd_driver);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
q40kbd_device = platform_device_alloc("q40kbd", -1);
|
||||
if (!q40kbd_device)
|
||||
goto err_unregister_driver;
|
||||
|
||||
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)
|
||||
{
|
||||
platform_device_unregister(q40kbd_device);
|
||||
platform_driver_unregister(&q40kbd_driver);
|
||||
}
|
||||
|
||||
module_init(q40kbd_init);
|
||||
|
|
|
@ -141,8 +141,8 @@ struct reverse_heartbeat {
|
|||
};
|
||||
|
||||
struct ibmasm_remote {
|
||||
struct input_dev keybd_dev;
|
||||
struct input_dev mouse_dev;
|
||||
struct input_dev *keybd_dev;
|
||||
struct input_dev *mouse_dev;
|
||||
};
|
||||
|
||||
struct service_processor {
|
||||
|
@ -157,7 +157,7 @@ struct service_processor {
|
|||
char dirname[IBMASM_NAME_SIZE];
|
||||
char devname[IBMASM_NAME_SIZE];
|
||||
unsigned int number;
|
||||
struct ibmasm_remote *remote;
|
||||
struct ibmasm_remote remote;
|
||||
int serial_line;
|
||||
struct device *dev;
|
||||
};
|
||||
|
|
|
@ -203,9 +203,9 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
|
|||
|
||||
print_input(&input);
|
||||
if (input.type == INPUT_TYPE_MOUSE) {
|
||||
send_mouse_event(&sp->remote->mouse_dev, regs, &input);
|
||||
send_mouse_event(sp->remote.mouse_dev, regs, &input);
|
||||
} else if (input.type == INPUT_TYPE_KEYBOARD) {
|
||||
send_keyboard_event(&sp->remote->keybd_dev, regs, &input);
|
||||
send_keyboard_event(sp->remote.keybd_dev, regs, &input);
|
||||
} else
|
||||
break;
|
||||
|
||||
|
@ -217,56 +217,70 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
|
|||
int ibmasm_init_remote_input_dev(struct service_processor *sp)
|
||||
{
|
||||
/* set up the mouse input device */
|
||||
struct ibmasm_remote *remote;
|
||||
struct input_dev *mouse_dev, *keybd_dev;
|
||||
struct pci_dev *pdev = to_pci_dev(sp->dev);
|
||||
int error = -ENOMEM;
|
||||
int i;
|
||||
|
||||
sp->remote = remote = kmalloc(sizeof(*remote), GFP_KERNEL);
|
||||
if (!remote)
|
||||
return -ENOMEM;
|
||||
sp->remote.mouse_dev = mouse_dev = input_allocate_device();
|
||||
sp->remote.keybd_dev = keybd_dev = input_allocate_device();
|
||||
|
||||
memset(remote, 0, sizeof(*remote));
|
||||
if (!mouse_dev || !keybd_dev)
|
||||
goto err_free_devices;
|
||||
|
||||
remote->mouse_dev.private = remote;
|
||||
init_input_dev(&remote->mouse_dev);
|
||||
remote->mouse_dev.id.vendor = pdev->vendor;
|
||||
remote->mouse_dev.id.product = pdev->device;
|
||||
remote->mouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
|
||||
remote->mouse_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
|
||||
mouse_dev->id.bustype = BUS_PCI;
|
||||
mouse_dev->id.vendor = pdev->vendor;
|
||||
mouse_dev->id.product = pdev->device;
|
||||
mouse_dev->id.version = 1;
|
||||
mouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
|
||||
mouse_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
|
||||
BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
|
||||
set_bit(BTN_TOUCH, remote->mouse_dev.keybit);
|
||||
remote->mouse_dev.name = remote_mouse_name;
|
||||
input_set_abs_params(&remote->mouse_dev, ABS_X, 0, xmax, 0, 0);
|
||||
input_set_abs_params(&remote->mouse_dev, ABS_Y, 0, ymax, 0, 0);
|
||||
set_bit(BTN_TOUCH, mouse_dev->keybit);
|
||||
mouse_dev->name = remote_mouse_name;
|
||||
input_set_abs_params(mouse_dev, ABS_X, 0, xmax, 0, 0);
|
||||
input_set_abs_params(mouse_dev, ABS_Y, 0, ymax, 0, 0);
|
||||
|
||||
remote->keybd_dev.private = remote;
|
||||
init_input_dev(&remote->keybd_dev);
|
||||
remote->keybd_dev.id.vendor = pdev->vendor;
|
||||
remote->keybd_dev.id.product = pdev->device;
|
||||
remote->keybd_dev.evbit[0] = BIT(EV_KEY);
|
||||
remote->keybd_dev.name = remote_keybd_name;
|
||||
mouse_dev->id.bustype = BUS_PCI;
|
||||
keybd_dev->id.vendor = pdev->vendor;
|
||||
keybd_dev->id.product = pdev->device;
|
||||
mouse_dev->id.version = 2;
|
||||
keybd_dev->evbit[0] = BIT(EV_KEY);
|
||||
keybd_dev->name = remote_keybd_name;
|
||||
|
||||
for (i=0; i<XLATE_SIZE; i++) {
|
||||
for (i = 0; i < XLATE_SIZE; i++) {
|
||||
if (xlate_high[i])
|
||||
set_bit(xlate_high[i], remote->keybd_dev.keybit);
|
||||
set_bit(xlate_high[i], keybd_dev->keybit);
|
||||
if (xlate[i])
|
||||
set_bit(xlate[i], remote->keybd_dev.keybit);
|
||||
set_bit(xlate[i], keybd_dev->keybit);
|
||||
}
|
||||
|
||||
input_register_device(&remote->mouse_dev);
|
||||
input_register_device(&remote->keybd_dev);
|
||||
error = input_register_device(mouse_dev);
|
||||
if (error)
|
||||
goto err_free_devices;
|
||||
|
||||
error = input_register_device(keybd_dev);
|
||||
if (error)
|
||||
goto err_unregister_mouse_dev;
|
||||
|
||||
enable_mouse_interrupts(sp);
|
||||
|
||||
printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_mouse_dev:
|
||||
input_unregister_device(mouse_dev);
|
||||
err_free_devices:
|
||||
input_free_device(mouse_dev);
|
||||
input_free_device(keybd_dev);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void ibmasm_free_remote_input_dev(struct service_processor *sp)
|
||||
{
|
||||
disable_mouse_interrupts(sp);
|
||||
input_unregister_device(&sp->remote->keybd_dev);
|
||||
input_unregister_device(&sp->remote->mouse_dev);
|
||||
kfree(sp->remote);
|
||||
input_unregister_device(sp->remote.mouse_dev);
|
||||
input_unregister_device(sp->remote.keybd_dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Copyright (C) 2005 Stelian Pop (stelian@popies.net)
|
||||
* Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
|
||||
* Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
|
||||
* Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
|
||||
*
|
||||
* Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
|
||||
*
|
||||
|
@ -38,6 +39,11 @@
|
|||
/* Apple has powerbooks which have the keyboard with different Product IDs */
|
||||
#define APPLE_VENDOR_ID 0x05AC
|
||||
|
||||
/* These names come from Info.plist in AppleUSBTrackpad.kext */
|
||||
#define GEYSER_ANSI_PRODUCT_ID 0x0214
|
||||
#define GEYSER_ISO_PRODUCT_ID 0x0215
|
||||
#define GEYSER_JIS_PRODUCT_ID 0x0216
|
||||
|
||||
#define ATP_DEVICE(prod) \
|
||||
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
|
||||
USB_DEVICE_ID_MATCH_INT_CLASS | \
|
||||
|
@ -53,13 +59,17 @@ static struct usb_device_id atp_table [] = {
|
|||
{ ATP_DEVICE(0x020F) },
|
||||
{ ATP_DEVICE(0x030A) },
|
||||
{ ATP_DEVICE(0x030B) },
|
||||
{ } /* Terminating entry */
|
||||
|
||||
/* PowerBooks Oct 2005 */
|
||||
{ ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
|
||||
{ ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
|
||||
{ ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
|
||||
|
||||
/* Terminating entry */
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE (usb, atp_table);
|
||||
|
||||
/* size of a USB urb transfer */
|
||||
#define ATP_DATASIZE 81
|
||||
|
||||
/*
|
||||
* number of sensors. Note that only 16 instead of 26 X (horizontal)
|
||||
* sensors exist on 12" and 15" PowerBooks. All models have 16 Y
|
||||
|
@ -108,6 +118,8 @@ struct atp {
|
|||
signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
|
||||
/* accumulated sensors */
|
||||
int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
|
||||
int overflowwarn; /* overflow warning printed? */
|
||||
int datalen; /* size of an USB urb transfer */
|
||||
};
|
||||
|
||||
#define dbg_dump(msg, tab) \
|
||||
|
@ -124,7 +136,7 @@ struct atp {
|
|||
if (debug) printk(format, ##a); \
|
||||
} while (0)
|
||||
|
||||
MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
|
||||
MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
|
||||
MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
@ -132,6 +144,16 @@ static int debug = 1;
|
|||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Activate debugging output");
|
||||
|
||||
/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
|
||||
static inline int atp_is_geyser_2(struct atp *dev)
|
||||
{
|
||||
int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct);
|
||||
|
||||
return (productId == GEYSER_ANSI_PRODUCT_ID) ||
|
||||
(productId == GEYSER_ISO_PRODUCT_ID) ||
|
||||
(productId == GEYSER_JIS_PRODUCT_ID);
|
||||
}
|
||||
|
||||
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
|
||||
int *z, int *fingers)
|
||||
{
|
||||
|
@ -168,13 +190,20 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers)
|
|||
static void atp_complete(struct urb* urb, struct pt_regs* regs)
|
||||
{
|
||||
int x, y, x_z, y_z, x_f, y_f;
|
||||
int retval, i;
|
||||
int retval, i, j;
|
||||
struct atp *dev = urb->context;
|
||||
|
||||
switch (urb->status) {
|
||||
case 0:
|
||||
/* success */
|
||||
break;
|
||||
case -EOVERFLOW:
|
||||
if(!dev->overflowwarn) {
|
||||
printk("appletouch: OVERFLOW with data "
|
||||
"length %d, actual length is %d\n",
|
||||
dev->datalen, dev->urb->actual_length);
|
||||
dev->overflowwarn = 1;
|
||||
}
|
||||
case -ECONNRESET:
|
||||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
|
@ -189,23 +218,45 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
|
|||
}
|
||||
|
||||
/* drop incomplete datasets */
|
||||
if (dev->urb->actual_length != ATP_DATASIZE) {
|
||||
if (dev->urb->actual_length != dev->datalen) {
|
||||
dprintk("appletouch: incomplete data package.\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* reorder the sensors values */
|
||||
for (i = 0; i < 8; i++) {
|
||||
/* X values */
|
||||
dev->xy_cur[i ] = dev->data[5 * i + 2];
|
||||
dev->xy_cur[i + 8] = dev->data[5 * i + 4];
|
||||
dev->xy_cur[i + 16] = dev->data[5 * i + 42];
|
||||
if (i < 2)
|
||||
dev->xy_cur[i + 24] = dev->data[5 * i + 44];
|
||||
if (atp_is_geyser_2(dev)) {
|
||||
memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
|
||||
|
||||
/* Y values */
|
||||
dev->xy_cur[i + 26] = dev->data[5 * i + 1];
|
||||
dev->xy_cur[i + 34] = dev->data[5 * i + 3];
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
|
|
@ -681,6 +681,21 @@ static char *keys[KEY_MAX + 1] = {
|
|||
[KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
|
||||
[KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
|
||||
[KEY_DOCUMENTS] = "Documents",
|
||||
[KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC",
|
||||
[KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2",
|
||||
[KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D",
|
||||
[KEY_FN_E] = "Fn+E", [KEY_FN_F] = "Fn+F",
|
||||
[KEY_FN_S] = "Fn+S",
|
||||
[KEY_FN_F1] = "Fn+F1", [KEY_FN_F2] = "Fn+F2",
|
||||
[KEY_FN_F3] = "Fn+F3", [KEY_FN_F4] = "Fn+F4",
|
||||
[KEY_FN_F5] = "Fn+F5", [KEY_FN_F6] = "Fn+F6",
|
||||
[KEY_FN_F7] = "Fn+F7", [KEY_FN_F8] = "Fn+F8",
|
||||
[KEY_FN_F9] = "Fn+F9", [KEY_FN_F10] = "Fn+F10",
|
||||
[KEY_FN_F11] = "Fn+F11", [KEY_FN_F12] = "Fn+F12",
|
||||
[KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle",
|
||||
[KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
|
||||
[KEY_KBDILLUMUP] = "KbdIlluminationUp",
|
||||
[KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
|
||||
};
|
||||
|
||||
static char *relatives[REL_MAX + 1] = {
|
||||
|
|
Loading…
Reference in New Issue