Merge git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
This commit is contained in:
commit
b9abaa3fb7
22 changed files with 1042 additions and 630 deletions
|
@ -3,7 +3,7 @@ Apple Touchpad Driver (appletouch)
|
||||||
Copyright (C) 2005 Stelian Pop <stelian@popies.net>
|
Copyright (C) 2005 Stelian Pop <stelian@popies.net>
|
||||||
|
|
||||||
appletouch is a Linux kernel driver for the USB touchpad found on post
|
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
|
This driver is derived from Johannes Berg's appletrackpad driver[1], but it has
|
||||||
been improved in some areas:
|
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,
|
Credits go to Johannes Berg for reverse-engineering the touchpad protocol,
|
||||||
Frank Arnold for further improvements, and Alex Harper for some additional
|
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:
|
Usage:
|
||||||
------
|
------
|
||||||
|
|
|
@ -146,6 +146,7 @@ static int evdev_open(struct inode * inode, struct file * file)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
|
|
||||||
struct input_event_compat {
|
struct input_event_compat {
|
||||||
struct compat_timeval time;
|
struct compat_timeval time;
|
||||||
__u16 type;
|
__u16 type;
|
||||||
|
@ -165,22 +166,80 @@ struct input_event_compat {
|
||||||
# define COMPAT_TEST test_thread_flag(TIF_32BIT)
|
# define COMPAT_TEST test_thread_flag(TIF_32BIT)
|
||||||
#endif
|
#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;
|
return COMPAT_TEST ?
|
||||||
struct input_event_compat event;
|
sizeof(struct input_event_compat) : sizeof(struct input_event);
|
||||||
int retval = 0;
|
}
|
||||||
|
|
||||||
while (retval < count) {
|
static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
|
||||||
if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat)))
|
{
|
||||||
|
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;
|
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)
|
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;
|
struct input_event event;
|
||||||
int retval = 0;
|
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)
|
if (!list->evdev->exist)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) {
|
while (retval < 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,
|
if (evdev_event_from_user(buffer + retval, &event))
|
||||||
sizeof(struct input_event_compat))) return -EFAULT;
|
return -EFAULT;
|
||||||
list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
|
input_event(list->evdev->handle.dev, event.type, event.code, event.value);
|
||||||
retval += sizeof(struct input_event_compat);
|
retval += evdev_event_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static ssize_t evdev_read(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;
|
struct evdev_list *list = file->private_data;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
if (count < evdev_event_size())
|
||||||
if (COMPAT_TEST)
|
|
||||||
return evdev_read_compat(file, buffer, count, ppos);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (count < sizeof(struct input_event))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
|
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)
|
if (!list->evdev->exist)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
while (list->head != list->tail && retval + sizeof(struct input_event) <= count) {
|
while (list->head != list->tail && retval + evdev_event_size() <= count) {
|
||||||
if (copy_to_user(buffer + retval, list->buffer + list->tail,
|
|
||||||
sizeof(struct input_event))) return -EFAULT;
|
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);
|
list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
|
||||||
retval += sizeof(struct input_event);
|
retval += evdev_event_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -290,17 +304,95 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
|
||||||
(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
|
(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_list *list = file->private_data;
|
||||||
struct evdev *evdev = list->evdev;
|
struct evdev *evdev = list->evdev;
|
||||||
struct input_dev *dev = evdev->handle.dev;
|
struct input_dev *dev = evdev->handle.dev;
|
||||||
struct input_absinfo abs;
|
struct input_absinfo abs;
|
||||||
void __user *p = (void __user *)arg;
|
int __user *ip = (int __user *)p;
|
||||||
int __user *ip = (int __user *)arg;
|
|
||||||
int i, t, u, v;
|
int i, t, u, v;
|
||||||
|
|
||||||
if (!evdev->exist) return -ENODEV;
|
if (!evdev->exist)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
switch (cmd) {
|
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);
|
return put_user(EV_VERSION, ip);
|
||||||
|
|
||||||
case EVIOCGID:
|
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:
|
case EVIOCGKEYCODE:
|
||||||
if (get_user(t, ip)) return -EFAULT;
|
if (get_user(t, ip))
|
||||||
if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
|
return -EFAULT;
|
||||||
if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) 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;
|
return 0;
|
||||||
|
|
||||||
case EVIOCSKEYCODE:
|
case EVIOCSKEYCODE:
|
||||||
if (get_user(t, ip)) return -EFAULT;
|
if (get_user(t, ip))
|
||||||
if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
|
return -EFAULT;
|
||||||
if (get_user(v, ip + 1)) return -EFAULT;
|
if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
|
||||||
if (v < 0 || v > KEY_MAX) return -EINVAL;
|
return -EINVAL;
|
||||||
if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) 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);
|
u = SET_INPUT_KEYCODE(dev, t, v);
|
||||||
clear_bit(u, dev->keybit);
|
clear_bit(u, dev->keybit);
|
||||||
set_bit(v, dev->keybit);
|
set_bit(v, dev->keybit);
|
||||||
for (i = 0; i < dev->keycodemax; i++)
|
for (i = 0; i < dev->keycodemax; i++)
|
||||||
if (INPUT_KEYCODE(dev,i) == u)
|
if (INPUT_KEYCODE(dev, i) == u)
|
||||||
set_bit(u, dev->keybit);
|
set_bit(u, dev->keybit);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case EVIOCSFF:
|
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)))
|
if (copy_from_user(&effect, p, sizeof(effect)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
err = dev->upload_effect(dev, &effect);
|
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 -EFAULT;
|
||||||
return err;
|
return err;
|
||||||
}
|
} else
|
||||||
else return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
|
||||||
case EVIOCRMFF:
|
case EVIOCRMFF:
|
||||||
if (dev->erase_effect) {
|
if (!dev->erase_effect)
|
||||||
return dev->erase_effect(dev, (int)arg);
|
return -ENOSYS;
|
||||||
}
|
|
||||||
else return -ENOSYS;
|
return dev->erase_effect(dev, (int)(unsigned long) p);
|
||||||
|
|
||||||
case EVIOCGEFFECTS:
|
case EVIOCGEFFECTS:
|
||||||
if (put_user(dev->ff_effects_max, ip))
|
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;
|
return 0;
|
||||||
|
|
||||||
case EVIOCGRAB:
|
case EVIOCGRAB:
|
||||||
if (arg) {
|
if (p) {
|
||||||
if (evdev->grab)
|
if (evdev->grab)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
if (input_grab_device(&evdev->handle))
|
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;
|
case EV_SW: bits = dev->swbit; len = SW_MAX; break;
|
||||||
default: return -EINVAL;
|
default: return -EINVAL;
|
||||||
}
|
}
|
||||||
len = NBITS(len) * sizeof(long);
|
return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
|
||||||
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
|
|
||||||
return copy_to_user(p, bits, len) ? -EFAULT : len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
|
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
|
||||||
int len;
|
return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
|
||||||
len = NBITS(KEY_MAX) * sizeof(long);
|
p, compat_mode);
|
||||||
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(EVIOCGLED(0))) {
|
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
|
||||||
int len;
|
return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
|
||||||
len = NBITS(LED_MAX) * sizeof(long);
|
p, compat_mode);
|
||||||
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(EVIOCGSND(0))) {
|
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
|
||||||
int len;
|
return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
|
||||||
len = NBITS(SND_MAX) * sizeof(long);
|
p, compat_mode);
|
||||||
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(EVIOCGSW(0))) {
|
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
|
||||||
int len;
|
return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
|
||||||
len = NBITS(SW_MAX) * sizeof(long);
|
p, compat_mode);
|
||||||
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(EVIOCGNAME(0))) {
|
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
|
||||||
int len;
|
return str_to_user(dev->name, _IOC_SIZE(cmd), p);
|
||||||
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))) {
|
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
|
||||||
int len;
|
return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
|
||||||
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))) {
|
if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
|
||||||
int len;
|
return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
|
||||||
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))) {
|
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;
|
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
|
#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_compat(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct evdev_list *list = file->private_data;
|
return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -52,5 +52,12 @@ config GAMEPORT_EMU10K1
|
||||||
config GAMEPORT_FM801
|
config GAMEPORT_FM801
|
||||||
tristate "ForteMedia FM801 gameport support"
|
tristate "ForteMedia FM801 gameport support"
|
||||||
depends on PCI
|
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
|
endif
|
||||||
|
|
|
@ -321,7 +321,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case ATKBD_RET_BAT:
|
case ATKBD_RET_BAT:
|
||||||
atkbd->enabled = 0;
|
atkbd->enabled = 0;
|
||||||
serio_rescan(atkbd->ps2dev.serio);
|
serio_reconnect(atkbd->ps2dev.serio);
|
||||||
goto out;
|
goto out;
|
||||||
case ATKBD_RET_EMUL0:
|
case ATKBD_RET_EMUL0:
|
||||||
atkbd->emul = 1;
|
atkbd->emul = 1;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
#include <asm/machdep.h>
|
#include <asm/machdep.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>");
|
||||||
MODULE_DESCRIPTION("m68k beeper driver");
|
MODULE_DESCRIPTION("m68k beeper driver");
|
||||||
MODULE_LICENSE("GPL");
|
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)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init m68kspkr_init(void)
|
static int __devinit m68kspkr_probe(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
if (!mach_beep) {
|
struct input_dev *input_dev;
|
||||||
printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
|
int err;
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
m68kspkr_dev = input_allocate_device();
|
input_dev = input_allocate_device();
|
||||||
if (!m68kspkr_dev)
|
if (!input_dev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
m68kspkr_dev->name = "m68k beeper";
|
input_dev->name = "m68k beeper";
|
||||||
m68kspkr_dev->phys = "m68k/generic";
|
input_dev->phys = "m68k/generic";
|
||||||
m68kspkr_dev->id.bustype = BUS_HOST;
|
input_dev->id.bustype = BUS_HOST;
|
||||||
m68kspkr_dev->id.vendor = 0x001f;
|
input_dev->id.vendor = 0x001f;
|
||||||
m68kspkr_dev->id.product = 0x0001;
|
input_dev->id.product = 0x0001;
|
||||||
m68kspkr_dev->id.version = 0x0100;
|
input_dev->id.version = 0x0100;
|
||||||
|
input_dev->cdev.dev = &dev->dev;
|
||||||
|
|
||||||
m68kspkr_dev->evbit[0] = BIT(EV_SND);
|
input_dev->evbit[0] = BIT(EV_SND);
|
||||||
m68kspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
|
input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
|
||||||
m68kspkr_dev->event = m68kspkr_event;
|
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;
|
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)
|
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);
|
module_init(m68kspkr_init);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
#include <asm/8253pit.h>
|
#include <asm/8253pit.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
@ -23,8 +24,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
||||||
MODULE_DESCRIPTION("PC Speaker beeper driver");
|
MODULE_DESCRIPTION("PC Speaker beeper driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
static struct input_dev *pcspkr_dev;
|
static struct platform_device *pcspkr_platform_device;
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(i8253_beep_lock);
|
static DEFINE_SPINLOCK(i8253_beep_lock);
|
||||||
|
|
||||||
static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
|
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;
|
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();
|
pcspkr_dev = input_allocate_device();
|
||||||
if (!pcspkr_dev)
|
if (!pcspkr_dev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -76,22 +79,93 @@ static int __init pcspkr_init(void)
|
||||||
pcspkr_dev->id.vendor = 0x001f;
|
pcspkr_dev->id.vendor = 0x001f;
|
||||||
pcspkr_dev->id.product = 0x0001;
|
pcspkr_dev->id.product = 0x0001;
|
||||||
pcspkr_dev->id.version = 0x0100;
|
pcspkr_dev->id.version = 0x0100;
|
||||||
|
pcspkr_dev->cdev.dev = &dev->dev;
|
||||||
|
|
||||||
pcspkr_dev->evbit[0] = BIT(EV_SND);
|
pcspkr_dev->evbit[0] = BIT(EV_SND);
|
||||||
pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
|
pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
|
||||||
pcspkr_dev->event = pcspkr_event;
|
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;
|
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 */
|
/* turn off the speaker */
|
||||||
pcspkr_event(NULL, EV_SND, SND_BELL, 0);
|
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_init(pcspkr_init);
|
||||||
module_exit(pcspkr_exit);
|
module_exit(pcspkr_exit);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/ebus.h>
|
#include <asm/ebus.h>
|
||||||
|
@ -20,22 +21,10 @@ MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
|
||||||
MODULE_DESCRIPTION("Sparc Speaker beeper driver");
|
MODULE_DESCRIPTION("Sparc Speaker beeper driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
const char *beep_name;
|
||||||
static unsigned long beep_iobase;
|
static unsigned long beep_iobase;
|
||||||
static struct input_dev *sparcspkr_dev;
|
static int (*beep_event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
|
||||||
|
static DEFINE_SPINLOCK(beep_lock);
|
||||||
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 ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
|
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
|
/* EBUS speaker only has on/off state, the frequency does not
|
||||||
* appear to be programmable.
|
* appear to be programmable.
|
||||||
*/
|
*/
|
||||||
if (count) {
|
if (beep_iobase & 0x2UL)
|
||||||
if (beep_iobase & 0x2UL)
|
outb(!!count, beep_iobase);
|
||||||
outb(1, beep_iobase);
|
else
|
||||||
else
|
outl(!!count, beep_iobase);
|
||||||
outl(1, beep_iobase);
|
|
||||||
} else {
|
|
||||||
if (beep_iobase & 0x2UL)
|
|
||||||
outb(0, beep_iobase);
|
|
||||||
else
|
|
||||||
outl(0, beep_iobase);
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&beep_lock, flags);
|
spin_unlock_irqrestore(&beep_lock, flags);
|
||||||
|
|
||||||
return 0;
|
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
|
#ifdef CONFIG_SPARC64
|
||||||
static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
|
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;
|
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();
|
input_dev = input_allocate_device();
|
||||||
if (!sparcspkr_dev)
|
if (!input_dev)
|
||||||
return -ENOMEM;
|
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";
|
input_dev->evbit[0] = BIT(EV_SND);
|
||||||
sparcspkr_dev->event = isa_spkr_event;
|
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;
|
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)
|
static int __init sparcspkr_init(void)
|
||||||
{
|
{
|
||||||
struct linux_ebus *ebus;
|
struct linux_ebus *ebus;
|
||||||
struct linux_ebus_device *edev = NULL;
|
struct linux_ebus_device *edev;
|
||||||
#ifdef CONFIG_SPARC64
|
#ifdef CONFIG_SPARC64
|
||||||
struct sparc_isa_bridge *isa_br;
|
struct sparc_isa_bridge *isa_br;
|
||||||
struct sparc_isa_device *isa_dev;
|
struct sparc_isa_device *isa_dev;
|
||||||
|
@ -160,8 +199,12 @@ static int __init sparcspkr_init(void)
|
||||||
|
|
||||||
for_each_ebus(ebus) {
|
for_each_ebus(ebus) {
|
||||||
for_each_ebusdev(edev, ebus) {
|
for_each_ebusdev(edev, ebus) {
|
||||||
if (!strcmp(edev->prom_name, "beep"))
|
if (!strcmp(edev->prom_name, "beep")) {
|
||||||
return init_ebus_beep(edev);
|
beep_name = "Sparc EBUS Speaker";
|
||||||
|
beep_event = ebus_spkr_event;
|
||||||
|
beep_iobase = edev->resource[0].start;
|
||||||
|
return sparcspkr_drv_init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SPARC64
|
#ifdef CONFIG_SPARC64
|
||||||
|
@ -170,8 +213,12 @@ static int __init sparcspkr_init(void)
|
||||||
/* A hack, the beep device's base lives in
|
/* A hack, the beep device's base lives in
|
||||||
* the DMA isa node.
|
* the DMA isa node.
|
||||||
*/
|
*/
|
||||||
if (!strcmp(isa_dev->prom_name, "dma"))
|
if (!strcmp(isa_dev->prom_name, "dma")) {
|
||||||
return init_isa_beep(isa_dev);
|
beep_name = "Sparc ISA Speaker";
|
||||||
|
beep_event = isa_spkr_event,
|
||||||
|
beep_iobase = isa_dev->resource.start;
|
||||||
|
return sparcspkr_drv_init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -181,7 +228,8 @@ static int __init sparcspkr_init(void)
|
||||||
|
|
||||||
static void __exit sparcspkr_exit(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);
|
module_init(sparcspkr_init);
|
||||||
|
|
|
@ -174,7 +174,7 @@ static u16 bios_pop_queue(void)
|
||||||
return regs.eax;
|
return regs.eax;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init bios_attach(void)
|
static void __devinit bios_attach(void)
|
||||||
{
|
{
|
||||||
struct regs regs;
|
struct regs regs;
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ static void bios_detach(void)
|
||||||
call_bios(®s);
|
call_bios(®s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 __init bios_get_cmos_address(void)
|
static u8 __devinit bios_get_cmos_address(void)
|
||||||
{
|
{
|
||||||
struct regs regs;
|
struct regs regs;
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ static u8 __init bios_get_cmos_address(void)
|
||||||
return regs.ecx;
|
return regs.ecx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 __init bios_get_default_setting(u8 subsys)
|
static u16 __devinit bios_get_default_setting(u8 subsys)
|
||||||
{
|
{
|
||||||
struct regs regs;
|
struct regs regs;
|
||||||
|
|
||||||
|
@ -296,6 +296,16 @@ static struct key_entry keymap_acer_aspire_1500[] = {
|
||||||
{ KE_END, 0 }
|
{ 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
|
* 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
|
* 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
|
.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, }
|
{ NULL, }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -348,7 +367,7 @@ static int __init select_keymap(void)
|
||||||
|
|
||||||
static struct input_dev *input_dev;
|
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;
|
const struct key_entry *key;
|
||||||
int error;
|
int error;
|
||||||
|
@ -447,6 +466,52 @@ static void poll_bios(unsigned long discard)
|
||||||
mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
|
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)
|
static int wistron_suspend(struct platform_device *dev, pm_message_t state)
|
||||||
{
|
{
|
||||||
del_timer_sync(&poll_timer);
|
del_timer_sync(&poll_timer);
|
||||||
|
@ -472,13 +537,20 @@ static int wistron_resume(struct platform_device *dev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define wistron_suspend NULL
|
||||||
|
#define wistron_resume NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct platform_driver wistron_driver = {
|
static struct platform_driver wistron_driver = {
|
||||||
.suspend = wistron_suspend,
|
|
||||||
.resume = wistron_resume,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "wistron-bios",
|
.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)
|
static int __init wb_module_init(void)
|
||||||
|
@ -493,55 +565,27 @@ static int __init wb_module_init(void)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
bios_attach();
|
|
||||||
cmos_address = bios_get_cmos_address();
|
|
||||||
|
|
||||||
err = platform_driver_register(&wistron_driver);
|
err = platform_driver_register(&wistron_driver);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_detach_bios;
|
goto err_unmap_bios;
|
||||||
|
|
||||||
wistron_device = platform_device_register_simple("wistron-bios", -1, NULL, 0);
|
wistron_device = platform_device_alloc("wistron-bios", -1);
|
||||||
if (IS_ERR(wistron_device)) {
|
if (!wistron_device) {
|
||||||
err = PTR_ERR(wistron_device);
|
err = -ENOMEM;
|
||||||
goto err_unregister_driver;
|
goto err_unregister_driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (have_wifi) {
|
err = platform_device_add(wistron_device);
|
||||||
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();
|
|
||||||
if (err)
|
if (err)
|
||||||
goto err_unregister_device;
|
goto err_free_device;
|
||||||
|
|
||||||
poll_bios(1); /* Flush stale event queue and arm timer */
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_unregister_device:
|
err_free_device:
|
||||||
platform_device_unregister(wistron_device);
|
platform_device_put(wistron_device);
|
||||||
err_unregister_driver:
|
err_unregister_driver:
|
||||||
platform_driver_unregister(&wistron_driver);
|
platform_driver_unregister(&wistron_driver);
|
||||||
err_detach_bios:
|
err_unmap_bios:
|
||||||
bios_detach();
|
|
||||||
unmap_bios();
|
unmap_bios();
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -549,11 +593,8 @@ static int __init wb_module_init(void)
|
||||||
|
|
||||||
static void __exit wb_module_exit(void)
|
static void __exit wb_module_exit(void)
|
||||||
{
|
{
|
||||||
del_timer_sync(&poll_timer);
|
|
||||||
input_unregister_device(input_dev);
|
|
||||||
platform_device_unregister(wistron_device);
|
platform_device_unregister(wistron_device);
|
||||||
platform_driver_unregister(&wistron_driver);
|
platform_driver_unregister(&wistron_driver);
|
||||||
bios_detach();
|
|
||||||
unmap_bios();
|
unmap_bios();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ static struct alps_model_info alps_model_data[] = {
|
||||||
{ { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
|
{ { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
|
||||||
{ { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
|
{ { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
|
||||||
{ { 0x53, 0x02, 0x14 }, 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, 0x0a }, 0xf8, 0xf8, 0 },
|
||||||
{ { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
|
{ { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
|
||||||
{ { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */
|
{ { 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"),
|
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 },
|
{ 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
|
||||||
{ 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
|
{ 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
|
||||||
{ 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
|
{ 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
|
||||||
|
{ 85, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
|
||||||
{ 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
|
{ 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
|
||||||
|
{ 87, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
|
||||||
{ 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
|
{ 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
|
||||||
{ 96, 0, 0 },
|
{ 96, 0, 0 },
|
||||||
{ 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
|
{ 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)
|
if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0)
|
||||||
return PSMOUSE_PS2PP;
|
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
|
* 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)
|
if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0)
|
||||||
return PSMOUSE_IMEX;
|
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)
|
if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse, set_properties) == 0)
|
||||||
return PSMOUSE_IMPS;
|
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
|
* Okay, all failed, we have a standard mouse here. The number of the buttons
|
||||||
* is still a question, though. We assume 3.
|
* is still a question, though. We assume 3.
|
||||||
|
@ -559,7 +557,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
|
||||||
* extensions.
|
* extensions.
|
||||||
*/
|
*/
|
||||||
psmouse_reset(psmouse);
|
psmouse_reset(psmouse);
|
||||||
ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return PSMOUSE_PS2;
|
return PSMOUSE_PS2;
|
||||||
|
|
|
@ -40,15 +40,15 @@ MODULE_LICENSE("GPL");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
|
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");
|
MODULE_PARM_DESC(xres, "Horizontal screen resolution");
|
||||||
|
|
||||||
static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
|
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");
|
MODULE_PARM_DESC(yres, "Vertical screen resolution");
|
||||||
|
|
||||||
static unsigned tap_time = 200;
|
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)");
|
MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)");
|
||||||
|
|
||||||
struct mousedev_hw_data {
|
struct mousedev_hw_data {
|
||||||
|
@ -155,7 +155,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case ABS_X:
|
case ABS_X:
|
||||||
size = dev->absmax[ABS_X] - dev->absmin[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->absmax[ABS_X]) value = dev->absmax[ABS_X];
|
||||||
if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X];
|
if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X];
|
||||||
mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size;
|
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:
|
case ABS_Y:
|
||||||
size = dev->absmax[ABS_Y] - dev->absmin[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->absmax[ABS_Y]) value = dev->absmax[ABS_Y];
|
||||||
if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y];
|
if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y];
|
||||||
mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size;
|
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.
|
* 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(0x55, 0x2fa); /* Any value except 9, ff or 36 */
|
||||||
outb_p(0xaa, 0x3fa); /* Inverse of 55 */
|
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(0x1b, 0x2fa); /* Inverse of e4 */
|
||||||
outb_p(0x0f, 0x390); /* Write index */
|
outb_p(0x0f, 0x390); /* Write index */
|
||||||
if (inb_p(0x391) != 0xe4) /* Config address found? */
|
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 */
|
outb_p(0x0d, 0x390); /* Write index */
|
||||||
ct82c710_iores.start = inb_p(0x391) << 2; /* Get mouse I/O address */
|
ct82c710_iores.start = inb_p(0x391) << 2; /* Get mouse I/O address */
|
||||||
|
@ -175,51 +175,88 @@ static int __init ct82c710_probe(void)
|
||||||
return 0;
|
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);
|
ct82c710_port->id.type = SERIO_8042;
|
||||||
if (serio) {
|
ct82c710_port->dev.parent = &dev->dev;
|
||||||
memset(serio, 0, sizeof(struct serio));
|
ct82c710_port->open = ct82c710_open;
|
||||||
serio->id.type = SERIO_8042;
|
ct82c710_port->close = ct82c710_close;
|
||||||
serio->open = ct82c710_open;
|
ct82c710_port->write = ct82c710_write;
|
||||||
serio->close = ct82c710_close;
|
strlcpy(ct82c710_port->name, "C&T 82c710 mouse port",
|
||||||
serio->write = ct82c710_write;
|
sizeof(ct82c710_port->name));
|
||||||
serio->dev.parent = &ct82c710_device->dev;
|
snprintf(ct82c710_port->phys, sizeof(ct82c710_port->phys),
|
||||||
strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name));
|
"isa%04lx/serio0", CT82C710_DATA);
|
||||||
snprintf(serio->phys, sizeof(serio->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)
|
static int __init ct82c710_init(void)
|
||||||
{
|
{
|
||||||
if (ct82c710_probe())
|
int error;
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1);
|
error = ct82c710_detect();
|
||||||
if (IS_ERR(ct82c710_device))
|
if (error)
|
||||||
return PTR_ERR(ct82c710_device);
|
return error;
|
||||||
|
|
||||||
if (!(ct82c710_port = ct82c710_allocate_port())) {
|
error = platform_driver_register(&ct82c710_driver);
|
||||||
platform_device_unregister(ct82c710_device);
|
if (error)
|
||||||
return -ENOMEM;
|
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);
|
serio_register_port(ct82c710_port);
|
||||||
|
|
||||||
printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n",
|
printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n",
|
||||||
CT82C710_DATA, CT82C710_IRQ);
|
CT82C710_DATA, CT82C710_IRQ);
|
||||||
|
|
||||||
return 0;
|
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)
|
static void __exit ct82c710_exit(void)
|
||||||
{
|
{
|
||||||
serio_unregister_port(ct82c710_port);
|
|
||||||
platform_device_unregister(ct82c710_device);
|
platform_device_unregister(ct82c710_device);
|
||||||
|
platform_driver_unregister(&ct82c710_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(ct82c710_init);
|
module_init(ct82c710_init);
|
||||||
|
|
|
@ -84,6 +84,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
|
||||||
DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
|
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"),
|
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.
|
* LCS/Telegraphics.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int __init i8042_check_mux(void)
|
static int __devinit i8042_check_mux(void)
|
||||||
{
|
{
|
||||||
unsigned char mux_version;
|
unsigned char mux_version;
|
||||||
|
|
||||||
|
@ -600,7 +600,7 @@ static int __init i8042_check_mux(void)
|
||||||
* the presence of an AUX interface.
|
* the presence of an AUX interface.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int __init i8042_check_aux(void)
|
static int __devinit i8042_check_aux(void)
|
||||||
{
|
{
|
||||||
unsigned char param;
|
unsigned char param;
|
||||||
static int i8042_check_aux_cookie;
|
static int i8042_check_aux_cookie;
|
||||||
|
@ -678,7 +678,7 @@ static int __init i8042_check_aux(void)
|
||||||
* registers it, and reports to the user.
|
* 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;
|
i8042_ctr &= ~port->disable;
|
||||||
|
|
||||||
|
@ -956,7 +956,6 @@ static int i8042_resume(struct platform_device *dev)
|
||||||
panic_blink = i8042_panic_blink;
|
panic_blink = i8042_panic_blink;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -969,16 +968,7 @@ static void i8042_shutdown(struct platform_device *dev)
|
||||||
i8042_controller_cleanup();
|
i8042_controller_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver i8042_driver = {
|
static int __devinit i8042_create_kbd_port(void)
|
||||||
.suspend = i8042_suspend,
|
|
||||||
.resume = i8042_resume,
|
|
||||||
.shutdown = i8042_shutdown,
|
|
||||||
.driver = {
|
|
||||||
.name = "i8042",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init i8042_create_kbd_port(void)
|
|
||||||
{
|
{
|
||||||
struct serio *serio;
|
struct serio *serio;
|
||||||
struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
|
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);
|
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 serio *serio;
|
||||||
struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
|
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);
|
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 serio *serio;
|
||||||
struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
|
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);
|
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 i, have_ports = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
dbg_init();
|
|
||||||
|
|
||||||
init_timer(&i8042_timer);
|
init_timer(&i8042_timer);
|
||||||
i8042_timer.function = i8042_timer_func;
|
i8042_timer.function = i8042_timer_func;
|
||||||
|
|
||||||
err = i8042_platform_init();
|
if (i8042_controller_init())
|
||||||
if (err)
|
return -ENODEV;
|
||||||
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_noaux && !i8042_check_aux()) {
|
if (!i8042_noaux && !i8042_check_aux()) {
|
||||||
if (!i8042_nomux && !i8042_check_mux()) {
|
if (!i8042_nomux && !i8042_check_mux()) {
|
||||||
|
@ -1113,30 +1082,23 @@ static int __init i8042_init(void)
|
||||||
|
|
||||||
if (!have_ports) {
|
if (!have_ports) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto err_unregister_device;
|
goto err_controller_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
|
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_unregister_ports:
|
err_unregister_ports:
|
||||||
for (i = 0; i < I8042_NUM_PORTS; i++)
|
for (i = 0; i < I8042_NUM_PORTS; i++)
|
||||||
if (i8042_ports[i].serio)
|
if (i8042_ports[i].serio)
|
||||||
serio_unregister_port(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:
|
err_controller_cleanup:
|
||||||
i8042_controller_cleanup();
|
i8042_controller_cleanup();
|
||||||
err_platform_exit:
|
|
||||||
i8042_platform_exit();
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit i8042_exit(void)
|
static int __devexit i8042_remove(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -1148,6 +1110,62 @@ static void __exit i8042_exit(void)
|
||||||
|
|
||||||
del_timer_sync(&i8042_timer);
|
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_device_unregister(i8042_platform_device);
|
||||||
platform_driver_unregister(&i8042_driver);
|
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;
|
struct serio *serio;
|
||||||
|
|
||||||
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
|
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
|
||||||
if (serio) {
|
if (serio) {
|
||||||
memset(serio, 0, sizeof(struct serio));
|
|
||||||
serio->id.type = SERIO_8042;
|
serio->id.type = SERIO_8042;
|
||||||
serio->write = maceps2_write;
|
serio->write = maceps2_write;
|
||||||
serio->open = maceps2_open;
|
serio->open = maceps2_open;
|
||||||
|
@ -138,24 +137,13 @@ static struct serio * __init maceps2_allocate_port(int idx)
|
||||||
return serio;
|
return serio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __devinit maceps2_probe(struct platform_device *dev)
|
||||||
static int __init maceps2_init(void)
|
|
||||||
{
|
{
|
||||||
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[0] = maceps2_allocate_port(0);
|
||||||
maceps2_port[1] = maceps2_allocate_port(1);
|
maceps2_port[1] = maceps2_allocate_port(1);
|
||||||
if (!maceps2_port[0] || !maceps2_port[1]) {
|
if (!maceps2_port[0] || !maceps2_port[1]) {
|
||||||
kfree(maceps2_port[0]);
|
kfree(maceps2_port[0]);
|
||||||
kfree(maceps2_port[1]);
|
kfree(maceps2_port[1]);
|
||||||
platform_device_unregister(maceps2_device);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,11 +153,59 @@ static int __init maceps2_init(void)
|
||||||
return 0;
|
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[0]);
|
||||||
serio_unregister_port(maceps2_port[1]);
|
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_device_unregister(maceps2_device);
|
||||||
|
platform_driver_unregister(&maceps2_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(maceps2_init);
|
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)
|
static void q40kbd_flush(void)
|
||||||
{
|
{
|
||||||
int maxread = 100;
|
int maxread = 100;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&q40kbd_lock, flags);
|
spin_lock_irqsave(&q40kbd_lock, flags);
|
||||||
|
|
||||||
while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
|
while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
|
||||||
master_inb(KEYCODE_REG);
|
master_inb(KEYCODE_REG);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&q40kbd_lock, flags);
|
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)) {
|
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);
|
printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
|
||||||
return -1;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* off we go */
|
/* off we go */
|
||||||
master_outb(-1, KEYBOARD_UNLOCK_REG);
|
master_outb(-1, KEYBOARD_UNLOCK_REG);
|
||||||
master_outb(1, KEY_IRQ_ENABLE_REG);
|
master_outb(1, KEY_IRQ_ENABLE_REG);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void q40kbd_close(struct serio *port)
|
static void q40kbd_close(struct serio *port)
|
||||||
|
@ -116,37 +116,18 @@ static void q40kbd_close(struct serio *port)
|
||||||
q40kbd_flush();
|
q40kbd_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct serio * __init q40kbd_allocate_port(void)
|
static int __devinit q40kbd_probe(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
struct serio *serio;
|
q40kbd_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
|
||||||
|
if (!q40kbd_port)
|
||||||
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);
|
|
||||||
return -ENOMEM;
|
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);
|
serio_register_port(q40kbd_port);
|
||||||
printk(KERN_INFO "serio: Q40 kbd registered\n");
|
printk(KERN_INFO "serio: Q40 kbd registered\n");
|
||||||
|
@ -154,10 +135,54 @@ static int __init q40kbd_init(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit q40kbd_exit(void)
|
static int __devexit q40kbd_remove(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
serio_unregister_port(q40kbd_port);
|
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_device_unregister(q40kbd_device);
|
||||||
|
platform_driver_unregister(&q40kbd_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(q40kbd_init);
|
module_init(q40kbd_init);
|
||||||
|
|
|
@ -141,8 +141,8 @@ struct reverse_heartbeat {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ibmasm_remote {
|
struct ibmasm_remote {
|
||||||
struct input_dev keybd_dev;
|
struct input_dev *keybd_dev;
|
||||||
struct input_dev mouse_dev;
|
struct input_dev *mouse_dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct service_processor {
|
struct service_processor {
|
||||||
|
@ -157,7 +157,7 @@ struct service_processor {
|
||||||
char dirname[IBMASM_NAME_SIZE];
|
char dirname[IBMASM_NAME_SIZE];
|
||||||
char devname[IBMASM_NAME_SIZE];
|
char devname[IBMASM_NAME_SIZE];
|
||||||
unsigned int number;
|
unsigned int number;
|
||||||
struct ibmasm_remote *remote;
|
struct ibmasm_remote remote;
|
||||||
int serial_line;
|
int serial_line;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
};
|
};
|
||||||
|
|
|
@ -203,9 +203,9 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
|
||||||
|
|
||||||
print_input(&input);
|
print_input(&input);
|
||||||
if (input.type == INPUT_TYPE_MOUSE) {
|
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) {
|
} 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
|
} else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -217,56 +217,70 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
|
||||||
int ibmasm_init_remote_input_dev(struct service_processor *sp)
|
int ibmasm_init_remote_input_dev(struct service_processor *sp)
|
||||||
{
|
{
|
||||||
/* set up the mouse input device */
|
/* 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);
|
struct pci_dev *pdev = to_pci_dev(sp->dev);
|
||||||
|
int error = -ENOMEM;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
sp->remote = remote = kmalloc(sizeof(*remote), GFP_KERNEL);
|
sp->remote.mouse_dev = mouse_dev = input_allocate_device();
|
||||||
if (!remote)
|
sp->remote.keybd_dev = keybd_dev = input_allocate_device();
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
memset(remote, 0, sizeof(*remote));
|
if (!mouse_dev || !keybd_dev)
|
||||||
|
goto err_free_devices;
|
||||||
|
|
||||||
remote->mouse_dev.private = remote;
|
mouse_dev->id.bustype = BUS_PCI;
|
||||||
init_input_dev(&remote->mouse_dev);
|
mouse_dev->id.vendor = pdev->vendor;
|
||||||
remote->mouse_dev.id.vendor = pdev->vendor;
|
mouse_dev->id.product = pdev->device;
|
||||||
remote->mouse_dev.id.product = pdev->device;
|
mouse_dev->id.version = 1;
|
||||||
remote->mouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
|
mouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
|
||||||
remote->mouse_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
|
mouse_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
|
||||||
BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
|
BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
|
||||||
set_bit(BTN_TOUCH, remote->mouse_dev.keybit);
|
set_bit(BTN_TOUCH, mouse_dev->keybit);
|
||||||
remote->mouse_dev.name = remote_mouse_name;
|
mouse_dev->name = remote_mouse_name;
|
||||||
input_set_abs_params(&remote->mouse_dev, ABS_X, 0, xmax, 0, 0);
|
input_set_abs_params(mouse_dev, ABS_X, 0, xmax, 0, 0);
|
||||||
input_set_abs_params(&remote->mouse_dev, ABS_Y, 0, ymax, 0, 0);
|
input_set_abs_params(mouse_dev, ABS_Y, 0, ymax, 0, 0);
|
||||||
|
|
||||||
remote->keybd_dev.private = remote;
|
mouse_dev->id.bustype = BUS_PCI;
|
||||||
init_input_dev(&remote->keybd_dev);
|
keybd_dev->id.vendor = pdev->vendor;
|
||||||
remote->keybd_dev.id.vendor = pdev->vendor;
|
keybd_dev->id.product = pdev->device;
|
||||||
remote->keybd_dev.id.product = pdev->device;
|
mouse_dev->id.version = 2;
|
||||||
remote->keybd_dev.evbit[0] = BIT(EV_KEY);
|
keybd_dev->evbit[0] = BIT(EV_KEY);
|
||||||
remote->keybd_dev.name = remote_keybd_name;
|
keybd_dev->name = remote_keybd_name;
|
||||||
|
|
||||||
for (i=0; i<XLATE_SIZE; i++) {
|
for (i = 0; i < XLATE_SIZE; i++) {
|
||||||
if (xlate_high[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])
|
if (xlate[i])
|
||||||
set_bit(xlate[i], remote->keybd_dev.keybit);
|
set_bit(xlate[i], keybd_dev->keybit);
|
||||||
}
|
}
|
||||||
|
|
||||||
input_register_device(&remote->mouse_dev);
|
error = input_register_device(mouse_dev);
|
||||||
input_register_device(&remote->keybd_dev);
|
if (error)
|
||||||
|
goto err_free_devices;
|
||||||
|
|
||||||
|
error = input_register_device(keybd_dev);
|
||||||
|
if (error)
|
||||||
|
goto err_unregister_mouse_dev;
|
||||||
|
|
||||||
enable_mouse_interrupts(sp);
|
enable_mouse_interrupts(sp);
|
||||||
|
|
||||||
printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number);
|
printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number);
|
||||||
|
|
||||||
return 0;
|
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)
|
void ibmasm_free_remote_input_dev(struct service_processor *sp)
|
||||||
{
|
{
|
||||||
disable_mouse_interrupts(sp);
|
disable_mouse_interrupts(sp);
|
||||||
input_unregister_device(&sp->remote->keybd_dev);
|
input_unregister_device(sp->remote.mouse_dev);
|
||||||
input_unregister_device(&sp->remote->mouse_dev);
|
input_unregister_device(sp->remote.keybd_dev);
|
||||||
kfree(sp->remote);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Copyright (C) 2005 Stelian Pop (stelian@popies.net)
|
* Copyright (C) 2005 Stelian Pop (stelian@popies.net)
|
||||||
* Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
|
* Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
|
||||||
* Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
|
* 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.
|
* 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 */
|
/* Apple has powerbooks which have the keyboard with different Product IDs */
|
||||||
#define APPLE_VENDOR_ID 0x05AC
|
#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) \
|
#define ATP_DEVICE(prod) \
|
||||||
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
|
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
|
||||||
USB_DEVICE_ID_MATCH_INT_CLASS | \
|
USB_DEVICE_ID_MATCH_INT_CLASS | \
|
||||||
|
@ -53,13 +59,17 @@ static struct usb_device_id atp_table [] = {
|
||||||
{ ATP_DEVICE(0x020F) },
|
{ ATP_DEVICE(0x020F) },
|
||||||
{ ATP_DEVICE(0x030A) },
|
{ ATP_DEVICE(0x030A) },
|
||||||
{ ATP_DEVICE(0x030B) },
|
{ 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);
|
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)
|
* number of sensors. Note that only 16 instead of 26 X (horizontal)
|
||||||
* sensors exist on 12" and 15" PowerBooks. All models have 16 Y
|
* 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];
|
signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
|
||||||
/* accumulated sensors */
|
/* accumulated sensors */
|
||||||
int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
|
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) \
|
#define dbg_dump(msg, tab) \
|
||||||
|
@ -124,7 +136,7 @@ struct atp {
|
||||||
if (debug) printk(format, ##a); \
|
if (debug) printk(format, ##a); \
|
||||||
} while (0)
|
} 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_DESCRIPTION("Apple PowerBooks USB touchpad driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
@ -132,6 +144,16 @@ static int debug = 1;
|
||||||
module_param(debug, int, 0644);
|
module_param(debug, int, 0644);
|
||||||
MODULE_PARM_DESC(debug, "Activate debugging output");
|
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,
|
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
|
||||||
int *z, int *fingers)
|
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)
|
static void atp_complete(struct urb* urb, struct pt_regs* regs)
|
||||||
{
|
{
|
||||||
int x, y, x_z, y_z, x_f, y_f;
|
int x, y, x_z, y_z, x_f, y_f;
|
||||||
int retval, i;
|
int retval, i, j;
|
||||||
struct atp *dev = urb->context;
|
struct atp *dev = urb->context;
|
||||||
|
|
||||||
switch (urb->status) {
|
switch (urb->status) {
|
||||||
case 0:
|
case 0:
|
||||||
/* success */
|
/* success */
|
||||||
break;
|
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 -ECONNRESET:
|
||||||
case -ENOENT:
|
case -ENOENT:
|
||||||
case -ESHUTDOWN:
|
case -ESHUTDOWN:
|
||||||
|
@ -189,23 +218,45 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* drop incomplete datasets */
|
/* drop incomplete datasets */
|
||||||
if (dev->urb->actual_length != ATP_DATASIZE) {
|
if (dev->urb->actual_length != dev->datalen) {
|
||||||
dprintk("appletouch: incomplete data package.\n");
|
dprintk("appletouch: incomplete data package.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reorder the sensors values */
|
/* reorder the sensors values */
|
||||||
for (i = 0; i < 8; i++) {
|
if (atp_is_geyser_2(dev)) {
|
||||||
/* X values */
|
memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
|
||||||
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];
|
* The values are laid out like this:
|
||||||
dev->xy_cur[i + 34] = dev->data[5 * i + 3];
|
* 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);
|
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;
|
dev->x_old = dev->y_old = -1;
|
||||||
memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
|
memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
|
||||||
|
|
||||||
/* 17" Powerbooks have 10 extra X sensors */
|
/* 17" Powerbooks have extra X sensors */
|
||||||
for (i = 16; i < ATP_XSENSORS; i++)
|
for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) {
|
||||||
if (dev->xy_cur[i]) {
|
if (!dev->xy_cur[i]) continue;
|
||||||
printk("appletouch: 17\" model detected.\n");
|
|
||||||
|
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,
|
input_set_abs_params(dev->input, ABS_X, 0,
|
||||||
(ATP_XSENSORS - 1) *
|
(ATP_XSENSORS - 1) *
|
||||||
ATP_XFACT - 1,
|
ATP_XFACT - 1,
|
||||||
ATP_FUZZ, 0);
|
ATP_FUZZ, 0);
|
||||||
break;
|
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
goto exit;
|
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));
|
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);
|
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->udev = udev;
|
||||||
dev->input = input_dev;
|
dev->input = input_dev;
|
||||||
|
dev->overflowwarn = 0;
|
||||||
|
dev->datalen = (atp_is_geyser_2(dev)?64:81);
|
||||||
|
|
||||||
dev->urb = usb_alloc_urb(0, GFP_KERNEL);
|
dev->urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
if (!dev->urb) {
|
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;
|
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);
|
&dev->urb->transfer_dma);
|
||||||
if (!dev->data) {
|
if (!dev->data) {
|
||||||
retval = -ENOMEM;
|
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_fill_int_urb(dev->urb, udev,
|
||||||
usb_rcvintpipe(udev, int_in_endpointAddr),
|
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));
|
usb_make_path(udev, dev->phys, sizeof(dev->phys));
|
||||||
strlcat(dev->phys, "/input0", 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);
|
set_bit(EV_ABS, input_dev->evbit);
|
||||||
|
|
||||||
/*
|
if (atp_is_geyser_2(dev)) {
|
||||||
* 12" and 15" Powerbooks only have 16 x sensors,
|
/*
|
||||||
* 17" models are detected later.
|
* Oct 2005 15" PowerBooks have 15 X sensors, 17" 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_X, 0,
|
||||||
input_set_abs_params(input_dev, ABS_Y, 0,
|
((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
|
||||||
(ATP_YSENSORS - 1) * ATP_YFACT - 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);
|
input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
|
||||||
|
|
||||||
set_bit(EV_KEY, input_dev->evbit);
|
set_bit(EV_KEY, input_dev->evbit);
|
||||||
|
@ -427,7 +500,7 @@ static void atp_disconnect(struct usb_interface *iface)
|
||||||
usb_kill_urb(dev->urb);
|
usb_kill_urb(dev->urb);
|
||||||
input_unregister_device(dev->input);
|
input_unregister_device(dev->input);
|
||||||
usb_free_urb(dev->urb);
|
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);
|
dev->data, dev->urb->transfer_dma);
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -681,6 +681,21 @@ static char *keys[KEY_MAX + 1] = {
|
||||||
[KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
|
[KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
|
||||||
[KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
|
[KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
|
||||||
[KEY_DOCUMENTS] = "Documents",
|
[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] = {
|
static char *relatives[REL_MAX + 1] = {
|
||||||
|
|
Loading…
Reference in a new issue