patch-2.4.0-test2 linux/drivers/usb/evdev.c

Next file: linux/drivers/usb/hid-debug.h
Previous file: linux/drivers/usb/dsbr100.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test1/linux/drivers/usb/evdev.c linux/drivers/usb/evdev.c
@@ -1,7 +1,7 @@
 /*
- *  evdev.c  Version 0.1
+ * $Id: evdev.c,v 1.10 2000/06/23 09:23:00 vojtech Exp $
  *
- *  Copyright (c) 1999 Vojtech Pavlik
+ *  Copyright (c) 1999-2000 Vojtech Pavlik
  *
  *  Event char devices, giving access to raw input device events.
  *
@@ -39,7 +39,7 @@
 #include <linux/input.h>
 
 struct evdev {
-	int used;
+	int exist;
 	int open;
 	int minor;
 	struct input_handle handle;
@@ -72,8 +72,7 @@
 		list->buffer[list->head].value = value;
 		list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
 		
-		if (list->fasync)
-			kill_fasync(list->fasync, SIGIO, POLL_IN);
+		kill_fasync(&list->fasync, SIGIO, POLL_IN);
 
 		list = list->next;
 	}
@@ -100,18 +99,18 @@
 		listptr = &((*listptr)->next);
 	*listptr = (*listptr)->next;
 
-	if (!--list->evdev->open)
-		input_close_device(&list->evdev->handle);	
-	
-	if (!--list->evdev->used) {
-		input_unregister_minor(list->evdev->devfs);
-		evdev_table[list->evdev->minor] = NULL;
-		kfree(list->evdev);
+	if (!--list->evdev->open) {
+		if (list->evdev->exist) {
+			input_close_device(&list->evdev->handle);	
+		} else {
+			input_unregister_minor(list->evdev->devfs);
+			evdev_table[list->evdev->minor] = NULL;
+			kfree(list->evdev);
+		}
 	}
 
 	kfree(list);
 
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -123,12 +122,8 @@
 	if (i > EVDEV_MINORS || !evdev_table[i])
 		return -ENODEV;
 
-	MOD_INC_USE_COUNT;
-
-	if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) {
-		MOD_DEC_USE_COUNT;
+	if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
 		return -ENOMEM;
-	}
 	memset(list, 0, sizeof(struct evdev_list));
 
 	list->evdev = evdev_table[i];
@@ -137,10 +132,9 @@
 
 	file->private_data = list;
 
-	list->evdev->used++;
-
 	if (!list->evdev->open++)
-		input_open_device(&list->evdev->handle);	
+		if (list->evdev->exist)
+			input_open_device(&list->evdev->handle);	
 
 	return 0;
 }
@@ -207,14 +201,20 @@
 	struct evdev_list *list = file->private_data;
 	struct evdev *evdev = list->evdev;
 	struct input_dev *dev = evdev->handle.dev;
+	int retval;
 
 	switch (cmd) {
 
 		case EVIOCGVERSION:
-			return put_user(EV_VERSION, (__u32 *) arg);
+			return put_user(EV_VERSION, (int *) arg);
+
 		case EVIOCGID:
-			return copy_to_user(&dev->id, (void *) arg,
-						sizeof(struct input_id)) ? -EFAULT : 0;
+			if ((retval = put_user(dev->idbus,     ((short *) arg) + 0))) return retval;
+			if ((retval = put_user(dev->idvendor,  ((short *) arg) + 1))) return retval;
+			if ((retval = put_user(dev->idproduct, ((short *) arg) + 2))) return retval;
+			if ((retval = put_user(dev->idversion, ((short *) arg) + 3))) return retval;
+			return 0;
+
 		default:
 
 			if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ)
@@ -222,8 +222,8 @@
 
 			if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
 
-				long *bits = NULL;
-				int len = 0;
+				long *bits;
+				int len;
 
 				switch (_IOC_NR(cmd) & EV_MAX) {
 					case      0: bits = dev->evbit;  len = EV_MAX;  break;
@@ -235,20 +235,40 @@
 					default: return -EINVAL;
 				}
 				len = NBITS(len) * sizeof(long);
-				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-				return copy_to_user((void *) arg, bits, len) ? -EFAULT : len;
+				if (len > _IOC_SIZE(cmd)) {
+					printk(KERN_WARNING "evdev.c: Truncating bitfield length from %d to %d\n",
+						len, _IOC_SIZE(cmd));
+					len = _IOC_SIZE(cmd);
+				}
+				return copy_to_user((char *) arg, bits, len) ? -EFAULT : len;
 			}
 
 			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
-				int len = strlen(dev->name) + 1;
+				int len;
+				if (!dev->name) return 0;
+				len = strlen(dev->name) + 1;
 				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
 				return copy_to_user((char *) arg, dev->name, len) ? -EFAULT : len;
 			}
+
+			if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
+
+				int t = _IOC_NR(cmd) & ABS_MAX;
+
+				if ((retval = put_user(dev->abs[t],     ((int *) arg) + 0))) return retval;
+				if ((retval = put_user(dev->absmin[t],  ((int *) arg) + 1))) return retval;
+				if ((retval = put_user(dev->absmax[t],  ((int *) arg) + 2))) return retval;
+				if ((retval = put_user(dev->absfuzz[t], ((int *) arg) + 3))) return retval;
+				if ((retval = put_user(dev->absflat[t], ((int *) arg) + 4))) return retval;
+
+				return 0;
+			}
 	}
 	return -EINVAL;
 }
 
 static struct file_operations evdev_fops = {
+	owner:		THIS_MODULE,
 	read:		evdev_read,
 	write:		evdev_write,
 	poll:		evdev_poll,
@@ -282,11 +302,11 @@
 	evdev->handle.handler = handler;
 	evdev->handle.private = evdev;
 
-	evdev->used = 1;
+	evdev->exist = 1;
 
 	evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
 
-	printk("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;
 }
@@ -295,10 +315,11 @@
 {
 	struct evdev *evdev = handle->private;
 
-	if (evdev->open)
-		input_close_device(handle);
+	evdev->exist = 0;
 
-	if (!--evdev->used) {
+	if (evdev->open) {
+		input_close_device(handle);
+	} else {
 		input_unregister_minor(evdev->devfs);
 		evdev_table[evdev->minor] = NULL;
 		kfree(evdev);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)