summaryrefslogtreecommitdiff
path: root/drivers/input/evdev.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 20:18:34 -0800
committerLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 20:18:34 -0800
commit1d66e22e0f6b1cca563d240f90697b05860dca4d (patch)
tree9d8e32ccca080b5ca5a729f0ac472ee96a361ae9 /drivers/input/evdev.c
parent932f485f76f33b46e302fc390ee8e66529a2e5b4 (diff)
v2.4.9.8 -> v2.4.9.9
- Greg KH: start migration to new "min()/max()" - Roman Zippel: move affs over to "min()/max()". - Vojtech Pavlik: VIA update (make sure not to IRQ-unmask a vt82c576) - Jan Kara: quota bug-fix (don't decrement quota for non-counted inode) - Anton Altaparmakov: more NTFS updates - Al Viro: make nosuid/noexec/nodev be per-mount flags, not per-filesystem - Alan Cox: merge input/joystick layer differences, driver and alpha merge - Keith Owens: scsi Makefile cleanup - Trond Myklebust: fix oopsable race in locking code - Jean Tourrilhes: IrDA update
Diffstat (limited to 'drivers/input/evdev.c')
-rw-r--r--drivers/input/evdev.c70
1 files changed, 57 insertions, 13 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index d1df86bc9d08..f4164acc26d7 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -1,7 +1,7 @@
/*
- * $Id: evdev.c,v 1.10 2000/06/23 09:23:00 vojtech Exp $
+ * $Id: evdev.c,v 1.27 2001/05/28 09:06:44 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*
* Event char devices, giving access to raw input device events.
*
@@ -11,18 +11,18 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ *
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
* Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
@@ -72,7 +72,7 @@ static void evdev_event(struct input_handle *handle, unsigned int type, unsigned
list->buffer[list->head].code = code;
list->buffer[list->head].value = value;
list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
-
+
kill_fasync(&list->fasync, SIGIO, POLL_IN);
list = list->next;
@@ -104,7 +104,7 @@ static int evdev_release(struct inode * inode, struct file * file)
if (!--list->evdev->open) {
if (list->evdev->exist) {
- input_close_device(&list->evdev->handle);
+ input_close_device(&list->evdev->handle);
} else {
input_unregister_minor(list->evdev->devfs);
evdev_table[list->evdev->minor] = NULL;
@@ -138,14 +138,26 @@ static int evdev_open(struct inode * inode, struct file * file)
if (!list->evdev->open++)
if (list->evdev->exist)
- input_open_device(&list->evdev->handle);
+ input_open_device(&list->evdev->handle);
return 0;
}
static ssize_t evdev_write(struct file * file, const char * buffer, size_t count, loff_t *ppos)
{
- return -EINVAL;
+ struct evdev_list *list = file->private_data;
+ struct input_event event;
+ int retval = 0;
+
+ 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;
}
static ssize_t evdev_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
@@ -161,6 +173,10 @@ static ssize_t evdev_read(struct file * file, char * buffer, size_t count, loff_
while (list->head == list->tail) {
+ if (!list->evdev->exist) {
+ retval = -ENODEV;
+ break;
+ }
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
@@ -187,7 +203,7 @@ static ssize_t evdev_read(struct file * file, char * buffer, size_t count, loff_
retval += sizeof(struct input_event);
}
- return retval;
+ return retval;
}
/* No kernel lock - fine */
@@ -219,6 +235,32 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if ((retval = put_user(dev->idversion, ((short *) arg) + 3))) return retval;
return 0;
+ case EVIOCSFF:
+ if (dev->upload_effect) {
+ struct ff_effect effect;
+ int err;
+
+ if (copy_from_user((void*)(&effect), (void*)arg, sizeof(effect))) {
+ return -EINVAL;
+ }
+ err = dev->upload_effect(dev, &effect);
+ if (put_user(effect.id, &(((struct ff_effect*)arg)->id))) {
+ return -EINVAL;
+ }
+ return err;
+ }
+ else return -ENOSYS;
+
+ case EVIOCRMFF:
+ if (dev->erase_effect) {
+ return dev->erase_effect(dev, (int)arg);
+ }
+ else return -ENOSYS;
+
+ case EVIOCGEFFECTS:
+ put_user(dev->ff_effects_max, (int*) arg);
+ return 0;
+
default:
if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ)
@@ -236,6 +278,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
+ case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
default: return -EINVAL;
}
len = NBITS(len) * sizeof(long);
@@ -310,7 +353,7 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
- printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev->number);
+// printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev->number);
return &evdev->handle;
}
@@ -323,13 +366,14 @@ static void evdev_disconnect(struct input_handle *handle)
if (evdev->open) {
input_close_device(handle);
+ wake_up_interruptible(&evdev->wait);
} else {
input_unregister_minor(evdev->devfs);
evdev_table[evdev->minor] = NULL;
kfree(evdev);
}
}
-
+
static struct input_handler evdev_handler = {
event: evdev_event,
connect: evdev_connect,