Skip to contentSkip to conversation

Input class hook up to driver model/sysfs

RFT/C 2.5.70 Hanna Linder 8 participants 13 messages May 28, 2003 – Jun 5, 2003 Input drivers

lore
Share & tools
lore
#0 lore raw

I did this once before but due to some infrastructure changes it had to be written again. Here it is, pretty simple. Now you can see your input devices (except keyboard) listed under /sys/class/input like this (yes, I do have two mice attached). At the moment the dev file is created and it contains the hex value of the major and minor number.

root@w-hlinder2 root]# tree /sys/class/input
/sys/class/input
|-- mouse0
| `-- dev
`-- mouse1

    `-- dev

2 directories, 2 files
[root@w-hlinder2 root]# more /sys/class/input/mouse0/dev 0d20
[root@w-hlinder2 root]# more /sys/class/input/mouse1/dev 0d21
[root@w-hlinder2 root]# ls -al /dev/input/mouse0
crw------- 1 root root 13, 32 Apr 11 2002 /dev/input/mouse0
[root@w-hlinder2 root]# ls -al /dev/input/mouse1
crw------- 1 root root 13, 33 Apr 11 2002 /dev/input/mouse1

Please review the code and/or run with the code to let me know the rest works as planned. Thanks.

Hanna Linder
[email protected]
IBM Linux Technology Center
------------

 drivers/input/evdev.c    |   20 ++++++++++---
 drivers/input/input.c    |   69 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/input/joydev.c   |   22 ++++++++++----
 drivers/input/mousedev.c |   29 +++++++++++++------
 drivers/input/tsdev.c    |   22 ++++++++++----
 include/linux/input.h    |   15 ++++++++++
 6 files changed, 151 insertions(+), 26 deletions(-)
drivers/input/evdev.c +15 -5
diff -Nrup -Xdontdiff linux-2.5.70/drivers/input/evdev.c linux-input/drivers/input/evdev.c
@@ -79,7 +79,7 @@ static int evdev_flush(struct file * fil
 
 static void evdev_free(struct evdev *evdev)
 {
-	devfs_remove("input/event%d", evdev->minor);
+	input_unregister_class_dev("input/event%d", evdev->minor);
 	evdev_table[evdev->minor] = NULL;
 	kfree(evdev);
 }
@@ -94,8 +94,10 @@ static int evdev_release(struct inode * 
 	if (!--list->evdev->open) {
 		if (list->evdev->exist)
 			input_close_device(&list->evdev->handle);
-		else
+		else{
+			input_unregister_class_dev("input/event%d", list->evdev->minor);
 			evdev_free(list->evdev);
+		}
 	}
 
 	kfree(list);
@@ -374,6 +376,12 @@ static struct file_operations evdev_fops
 	.flush =	evdev_flush
 };
 
+static struct input_class_interface intf = {
+	.name = 	"input/event%d",
+	.mode = 	S_IFCHR | S_IRUGO | S_IWUSR,
+	.minor_base = 	EVDEV_MINOR_BASE,
+};
+
 static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct evdev *evdev;
@@ -402,8 +410,8 @@ static struct input_handle *evdev_connec
 
 	evdev_table[minor] = evdev;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
+	intf.minor = minor;
+	input_register_class_dev(dev, &intf);
 
 	return &evdev->handle;
 }
@@ -417,8 +425,10 @@ static void evdev_disconnect(struct inpu
 	if (evdev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&evdev->wait);
-	} else
+	} else {
+		input_unregister_class_dev("input/event%d", evdev->minor);
 		evdev_free(evdev);
+	}
 }
 
 static struct input_device_id evdev_ids[] = {
drivers/input/input.c +69 -0

81 lines not on this page · raw message

drivers/input/joydev.c +16 -6
diff -Nrup -Xdontdiff linux-2.5.70/drivers/input/joydev.c linux-input/drivers/input/joydev.c
@@ -143,7 +143,7 @@ static int joydev_fasync(int fd, struct 
 
 static void joydev_free(struct joydev *joydev)
 {
-	devfs_remove("js%d", joydev->minor);
+	input_unregister_class_dev("js%d", joydev->minor);
 	joydev_table[joydev->minor] = NULL;
 	kfree(joydev);
 }
@@ -159,8 +159,10 @@ static int joydev_release(struct inode *
 	if (!--list->joydev->open) {
 		if (list->joydev->exist)
 			input_close_device(&list->joydev->handle);
-		else
+		else{
+			input_unregister_class_dev("js%d", list->joydev->minor);
 			joydev_free(list->joydev);
+		}
 	}
 
 	kfree(list);
@@ -375,6 +377,12 @@ static struct file_operations joydev_fop
 	.fasync =	joydev_fasync,
 };
 
+static struct input_class_interface intf = {
+	.name = 	"js%d",
+	.mode = 	S_IFCHR | S_IRUGO | S_IWUSR,
+	.minor_base = 	JOYDEV_MINOR_BASE,
+};
+
 static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct joydev *joydev;
@@ -445,9 +453,9 @@ static struct input_handle *joydev_conne
 	}
 
 	joydev_table[minor] = joydev;
-	
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "js%d", minor);
+
+	intf.minor = minor;
+	input_register_class_dev(dev, &intf); 	
 
 	return &joydev->handle;
 }
@@ -460,8 +468,10 @@ static void joydev_disconnect(struct inp
 
 	if (joydev->open)
 		input_close_device(handle);	
-	else
+	else{
+		input_unregister_class_dev("js%d", joydev->minor);
 		joydev_free(joydev);
+	}
 }
 
 static struct input_device_id joydev_ids[] = {
drivers/input/mousedev.c +20 -9
diff -Nrup -Xdontdiff linux-2.5.70/drivers/input/mousedev.c linux-input/drivers/input/mousedev.c
@@ -173,7 +173,7 @@ static int mousedev_fasync(int fd, struc
 
 static void mousedev_free(struct mousedev *mousedev)
 {
-	devfs_remove("input/mouse%d", mousedev->minor);
+	input_unregister_class_dev("input/mouse%d", mousedev->minor);
 	mousedev_table[mousedev->minor] = NULL;
 	kfree(mousedev);
 }
@@ -188,8 +188,10 @@ static int mixdev_release(void)
 		if (!mousedev->open) {
 			if (mousedev->exist)
 				input_close_device(&mousedev->handle);
-			else
+			else {
+				input_unregister_class_dev("input/mouse%d",mousedev->minor);
 				mousedev_free(mousedev);
+			}
 		}
 	}
 
@@ -211,8 +213,10 @@ static int mousedev_release(struct inode
 		if (!mousedev_mix.open) {
 			if (list->mousedev->exist)
 				input_close_device(&list->mousedev->handle);
-			else
+			else{
+				input_unregister_class_dev("input/mouse%d", list->mousedev->minor);
 				mousedev_free(list->mousedev);
+			}
 		}
 	}
 	
@@ -402,6 +406,12 @@ struct file_operations mousedev_fops = {
 	.fasync =	mousedev_fasync,
 };
 
+static struct input_class_interface intf = {
+	.name =		"mouse%d",
+	.mode = 	S_IFCHR | S_IRUGO | S_IWUSR,
+	.minor_base = 	MOUSEDEV_MINOR_BASE,
+};
+
 static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct mousedev *mousedev;
@@ -433,8 +443,8 @@ static struct input_handle *mousedev_con
 
 	mousedev_table[minor] = mousedev;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
+	intf.minor = minor;
+	input_register_class_dev(dev, &intf);
 
 	return &mousedev->handle;
 }
@@ -450,6 +460,7 @@ static void mousedev_disconnect(struct i
 	} else {
 		if (mousedev_mix.open)
 			input_close_device(handle);
+		input_unregister_class_dev("input/mouse%d",mousedev->minor);
 		mousedev_free(mousedev);
 	}
 }
@@ -496,6 +507,7 @@ static struct miscdevice psaux_mouse = {
 
 static int __init mousedev_init(void)
 {
+
 	input_register_handler(&mousedev_handler);
 
 	memset(&mousedev_mix, 0, sizeof(struct mousedev));
@@ -505,9 +517,8 @@ static int __init mousedev_init(void)
 	mousedev_mix.exist = 1;
 	mousedev_mix.minor = MOUSEDEV_MIX;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
-
+	intf.minor = mousedev_mix.minor;
+	input_register_class_dev (mousedev_mix.handler.dev, &intf);
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
 	if (!(mousedev_mix.misc = !misc_register(&psaux_mouse)))
@@ -525,7 +536,7 @@ static void __exit mousedev_exit(void)
 	if (mousedev_mix.misc)
 		misc_deregister(&psaux_mouse);
 #endif
-	devfs_remove("input/mice");
+	input_unregister_class_dev("mouse%d", mousedev_mix.minor);
 	input_unregister_handler(&mousedev_handler);
 }
 
drivers/input/tsdev.c +16 -6
diff -Nrup -Xdontdiff linux-2.5.70/drivers/input/tsdev.c linux-input/drivers/input/tsdev.c
@@ -118,7 +118,7 @@ static int tsdev_open(struct inode *inod
 
 static void tsdev_free(struct tsdev *tsdev)
 {
-	devfs_remove("input/ts%d", tsdev->minor);
+	input_unregister_class_dev("input/ts%d", tsdev->minor);
 	tsdev_table[tsdev->minor] = NULL;
 	kfree(tsdev);
 }
@@ -133,8 +133,10 @@ static int tsdev_release(struct inode *i
 	if (!--list->tsdev->open) {
 		if (list->tsdev->exist)
 			input_close_device(&list->tsdev->handle);
-		else
+		else{
+			input_unregister_class_dev("input/ts%d",list->tsdev->minor);
 			tsdev_free(list->tsdev);
+		}
 	}
 	kfree(list);
 	return 0;
@@ -298,6 +300,12 @@ static void tsdev_event(struct input_han
 	wake_up_interruptible(&tsdev->wait);
 }
 
+static struct input_class_interface intf = {
+	.name =		"input/ts%d", 
+	.mode = 	S_IFCHRIS | S_IRUGO | S_IWUSR,
+	.minor_base = 	TSDEV_MINOR_BASE,
+};
+
 static struct input_handle *tsdev_connect(struct input_handler *handler,
 					  struct input_dev *dev,
 					  struct input_device_id *id)
@@ -330,9 +338,9 @@ static struct input_handle *tsdev_connec
 	tsdev->handle.private = tsdev;
 
 	tsdev_table[minor] = tsdev;
-	
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
+
+	intf.minor = minor;
+	input_register_class_dev(dev, &intf);	
 
 	return &tsdev->handle;
 }
@@ -346,8 +354,10 @@ static void tsdev_disconnect(struct inpu
 	if (tsdev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&tsdev->wait);
-	} else
+	} else {
+		input_unregister_class_dev("input/ts%d",tsdev->minor);
 		tsdev_free(tsdev);
+	}
 }
 
 static struct input_device_id tsdev_ids[] = {
include/linux/input.h +15 -0
diff -Nrup -Xdontdiff linux-2.5.70/include/linux/input.h linux-input/include/linux/input.h
@@ -12,6 +12,7 @@
 #ifdef __KERNEL__
 #include <linux/time.h>
 #include <linux/list.h>
+#include <linux/device.h>
 #else
 #include <sys/time.h>
 #include <sys/ioctl.h>
@@ -800,6 +801,9 @@ struct input_dev {
 
 	struct list_head	h_list;
 	struct list_head	node;
+
+	struct class_device class_dev;
+	unsigned minor;
 };
 
 /*
@@ -877,6 +881,14 @@ struct input_handle {
 	struct list_head	h_node;
 };
 
+struct input_class_interface {
+
+	char *name;
+	mode_t mode;
+	unsigned minor;
+	int minor_base; 
+};
+
 #define to_dev(n) container_of(n,struct input_dev,node)
 #define to_handler(n) container_of(n,struct input_handler,node);
 #define to_handle(n) container_of(n,struct input_handle,d_node)
@@ -888,6 +900,9 @@ void input_unregister_device(struct inpu
 void input_register_handler(struct input_handler *);
 void input_unregister_handler(struct input_handler *);
 
+void input_register_class_dev(struct input_dev *, struct input_class_interface *);
+void input_unregister_class_dev(char *, unsigned );
+
 int input_open_device(struct input_handle *);
 void input_close_device(struct input_handle *);
 
#1 lore raw

I probably should have included the same patch I tested huh? Here is the one that compiles this time! Viro, I have not made the changes you suggested yet. Just wanted to get the one I tested out.

Hanna

Quoted 26 lines · --On Tuesday, May 27, 2003 06:04:51 PM -0700 Hanna Linder <[email protected]>…

I did this once before but due to some infrastructure changes it had to be written again. Here it is, pretty simple. Now you can see your input devices (except keyboard) listed under /sys/class/input like this (yes, I do have two mice attached). At the moment the dev file is created and it contains the hex value of the major and minor number.

root@w-hlinder2 root]# tree /sys/class/input
/sys/class/input
| -- mouse0
| `-- dev
`-- mouse1

    `-- dev

2 directories, 2 files
[root@w-hlinder2 root]# more /sys/class/input/mouse0/dev 0d20
[root@w-hlinder2 root]# more /sys/class/input/mouse1/dev 0d21
[root@w-hlinder2 root]# ls -al /dev/input/mouse0
crw------- 1 root root 13, 32 Apr 11 2002 /dev/input/mouse0
[root@w-hlinder2 root]# ls -al /dev/input/mouse1
crw------- 1 root root 13, 33 Apr 11 2002 /dev/input/mouse1

Quoted 6 lines

Please review the code and/or run with the code to let me know the rest works as planned. Thanks.

Hanna Linder
[email protected]
IBM Linux Technology Center

drivers/input/evdev.c +15 -5
diff -Nrup -Xdontdiff linux-2.5.70/drivers/input/evdev.c linux-input/drivers/input/evdev.c
@@ -79,7 +79,7 @@ static int evdev_flush(struct file * fil
 
 static void evdev_free(struct evdev *evdev)
 {
-	devfs_remove("input/event%d", evdev->minor);
+	input_unregister_class_dev("input/event%d", evdev->minor);
 	evdev_table[evdev->minor] = NULL;
 	kfree(evdev);
 }
@@ -94,8 +94,10 @@ static int evdev_release(struct inode * 
 	if (!--list->evdev->open) {
 		if (list->evdev->exist)
 			input_close_device(&list->evdev->handle);
-		else
+		else{
+			input_unregister_class_dev("input/event%d", list->evdev->minor);
 			evdev_free(list->evdev);
+		}
 	}
 
 	kfree(list);
@@ -374,6 +376,12 @@ static struct file_operations evdev_fops
 	.flush =	evdev_flush
 };
 
+static struct input_class_interface intf = {
+	.name = 	"input/event%d",
+	.mode = 	S_IFCHR | S_IRUGO | S_IWUSR,
+	.minor_base = 	EVDEV_MINOR_BASE,
+};
+
 static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct evdev *evdev;
@@ -402,8 +410,8 @@ static struct input_handle *evdev_connec
 
 	evdev_table[minor] = evdev;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
+	intf.minor = minor;
+	input_register_class_dev(dev, &intf);
 
 	return &evdev->handle;
 }
@@ -417,8 +425,10 @@ static void evdev_disconnect(struct inpu
 	if (evdev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&evdev->wait);
-	} else
+	} else {
+		input_unregister_class_dev("input/event%d", evdev->minor);
 		evdev_free(evdev);
+	}
 }
 
 static struct input_device_id evdev_ids[] = {
drivers/input/input.c +69 -0

81 lines not on this page · raw message

drivers/input/joydev.c +16 -6
diff -Nrup -Xdontdiff linux-2.5.70/drivers/input/joydev.c linux-input/drivers/input/joydev.c
@@ -143,7 +143,7 @@ static int joydev_fasync(int fd, struct 
 
 static void joydev_free(struct joydev *joydev)
 {
-	devfs_remove("js%d", joydev->minor);
+	input_unregister_class_dev("js%d", joydev->minor);
 	joydev_table[joydev->minor] = NULL;
 	kfree(joydev);
 }
@@ -159,8 +159,10 @@ static int joydev_release(struct inode *
 	if (!--list->joydev->open) {
 		if (list->joydev->exist)
 			input_close_device(&list->joydev->handle);
-		else
+		else{
+			input_unregister_class_dev("js%d", list->joydev->minor);
 			joydev_free(list->joydev);
+		}
 	}
 
 	kfree(list);
@@ -375,6 +377,12 @@ static struct file_operations joydev_fop
 	.fasync =	joydev_fasync,
 };
 
+static struct input_class_interface intf = {
+	.name = 	"js%d",
+	.mode = 	S_IFCHR | S_IRUGO | S_IWUSR,
+	.minor_base = 	JOYDEV_MINOR_BASE,
+};
+
 static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct joydev *joydev;
@@ -445,9 +453,9 @@ static struct input_handle *joydev_conne
 	}
 
 	joydev_table[minor] = joydev;
-	
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "js%d", minor);
+
+	intf.minor = minor;
+	input_register_class_dev(dev, &intf); 	
 
 	return &joydev->handle;
 }
@@ -460,8 +468,10 @@ static void joydev_disconnect(struct inp
 
 	if (joydev->open)
 		input_close_device(handle);	
-	else
+	else{
+		input_unregister_class_dev("js%d", joydev->minor);
 		joydev_free(joydev);
+	}
 }
 
 static struct input_device_id joydev_ids[] = {
drivers/input/mousedev.c +18 -7
diff -Nrup -Xdontdiff linux-2.5.70/drivers/input/mousedev.c linux-input/drivers/input/mousedev.c
@@ -173,7 +173,7 @@ static int mousedev_fasync(int fd, struc
 
 static void mousedev_free(struct mousedev *mousedev)
 {
-	devfs_remove("input/mouse%d", mousedev->minor);
+	input_unregister_class_dev("input/mouse%d", mousedev->minor);
 	mousedev_table[mousedev->minor] = NULL;
 	kfree(mousedev);
 }
@@ -188,8 +188,10 @@ static int mixdev_release(void)
 		if (!mousedev->open) {
 			if (mousedev->exist)
 				input_close_device(&mousedev->handle);
-			else
+			else {
+				input_unregister_class_dev("input/mouse%d",mousedev->minor);
 				mousedev_free(mousedev);
+			}
 		}
 	}
 
@@ -211,8 +213,10 @@ static int mousedev_release(struct inode
 		if (!mousedev_mix.open) {
 			if (list->mousedev->exist)
 				input_close_device(&list->mousedev->handle);
-			else
+			else{
+				input_unregister_class_dev("input/mouse%d", list->mousedev->minor);
 				mousedev_free(list->mousedev);
+			}
 		}
 	}
 	
@@ -402,6 +406,12 @@ struct file_operations mousedev_fops = {
 	.fasync =	mousedev_fasync,
 };
 
+static struct input_class_interface intf = {
+	.name =		"mouse%d",
+	.mode = 	S_IFCHR | S_IRUGO | S_IWUSR,
+	.minor_base = 	MOUSEDEV_MINOR_BASE,
+};
+
 static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct mousedev *mousedev;
@@ -433,8 +443,8 @@ static struct input_handle *mousedev_con
 
 	mousedev_table[minor] = mousedev;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
+	intf.minor = minor;
+	input_register_class_dev(dev, &intf);
 
 	return &mousedev->handle;
 }
@@ -450,6 +460,7 @@ static void mousedev_disconnect(struct i
 	} else {
 		if (mousedev_mix.open)
 			input_close_device(handle);
+		input_unregister_class_dev("input/mouse%d",mousedev->minor);
 		mousedev_free(mousedev);
 	}
 }
@@ -505,8 +516,8 @@ static int __init mousedev_init(void)
 	mousedev_mix.exist = 1;
 	mousedev_mix.minor = MOUSEDEV_MIX;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), 
+		        S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
 
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
drivers/input/tsdev.c +16 -6
diff -Nrup -Xdontdiff linux-2.5.70/drivers/input/tsdev.c linux-input/drivers/input/tsdev.c
@@ -118,7 +118,7 @@ static int tsdev_open(struct inode *inod
 
 static void tsdev_free(struct tsdev *tsdev)
 {
-	devfs_remove("input/ts%d", tsdev->minor);
+	input_unregister_class_dev("input/ts%d", tsdev->minor);
 	tsdev_table[tsdev->minor] = NULL;
 	kfree(tsdev);
 }
@@ -133,8 +133,10 @@ static int tsdev_release(struct inode *i
 	if (!--list->tsdev->open) {
 		if (list->tsdev->exist)
 			input_close_device(&list->tsdev->handle);
-		else
+		else{
+			input_unregister_class_dev("input/ts%d",list->tsdev->minor);
 			tsdev_free(list->tsdev);
+		}
 	}
 	kfree(list);
 	return 0;
@@ -298,6 +300,12 @@ static void tsdev_event(struct input_han
 	wake_up_interruptible(&tsdev->wait);
 }
 
+static struct input_class_interface intf = {
+	.name =		"input/ts%d", 
+	.mode = 	S_IFCHRIS | S_IRUGO | S_IWUSR,
+	.minor_base = 	TSDEV_MINOR_BASE,
+};
+
 static struct input_handle *tsdev_connect(struct input_handler *handler,
 					  struct input_dev *dev,
 					  struct input_device_id *id)
@@ -330,9 +338,9 @@ static struct input_handle *tsdev_connec
 	tsdev->handle.private = tsdev;
 
 	tsdev_table[minor] = tsdev;
-	
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
+
+	intf.minor = minor;
+	input_register_class_dev(dev, &intf);	
 
 	return &tsdev->handle;
 }
@@ -346,8 +354,10 @@ static void tsdev_disconnect(struct inpu
 	if (tsdev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&tsdev->wait);
-	} else
+	} else {
+		input_unregister_class_dev("input/ts%d",tsdev->minor);
 		tsdev_free(tsdev);
+	}
 }
 
 static struct input_device_id tsdev_ids[] = {
include/linux/input.h +15 -0
diff -Nrup -Xdontdiff linux-2.5.70/include/linux/input.h linux-input/include/linux/input.h
@@ -12,6 +12,7 @@
 #ifdef __KERNEL__
 #include <linux/time.h>
 #include <linux/list.h>
+#include <linux/device.h>
 #else
 #include <sys/time.h>
 #include <sys/ioctl.h>
@@ -800,6 +801,9 @@ struct input_dev {
 
 	struct list_head	h_list;
 	struct list_head	node;
+
+	struct class_device class_dev;
+	unsigned minor;
 };
 
 /*
@@ -877,6 +881,14 @@ struct input_handle {
 	struct list_head	h_node;
 };
 
+struct input_class_interface {
+
+	char *name;
+	mode_t mode;
+	unsigned minor;
+	int minor_base; 
+};
+
 #define to_dev(n) container_of(n,struct input_dev,node)
 #define to_handler(n) container_of(n,struct input_handler,node);
 #define to_handle(n) container_of(n,struct input_handle,d_node)
@@ -888,6 +900,9 @@ void input_unregister_device(struct inpu
 void input_register_handler(struct input_handler *);
 void input_unregister_handler(struct input_handler *);
 
+void input_register_class_dev(struct input_dev *, struct input_class_interface *);
+void input_unregister_class_dev(char *, unsigned );
+
 int input_open_device(struct input_handle *);
 void input_close_device(struct input_handle *);
 
#2 lore raw
In reply to Hanna Linder
Quoted 7 lines · Hanna Linder

root@w-hlinder2 root]# tree /sys/class/input
/sys/class/input
|-- mouse0
| `-- dev
`-- mouse1

    `-- dev

What happened to /sys/class/input/mice? It should be present too.

Looks good, Al's point about not just calling kfree() on the kobject is correct, but you copied my tty code which has the same bug :)

Another minor comment:

Quoted 42 lines
drivers/input/evdev.c +12 -4
-	devfs_remove("input/event%d", evdev->minor);
+	input_unregister_class_dev("input/event%d", evdev->minor);
 	evdev_table[evdev->minor] = NULL;
 	kfree(evdev);
 }
@@ -94,8 +94,10 @@ static int evdev_release(struct inode * 
 	if (!--list->evdev->open) {
 		if (list->evdev->exist)
 			input_close_device(&list->evdev->handle);
-		else
+		else{
+			input_unregister_class_dev("input/event%d", list->evdev->minor);
 			evdev_free(list->evdev);
+		}
 	}
 
 	kfree(list);
@@ -374,6 +376,12 @@ static struct file_operations evdev_fops
 	.flush =	evdev_flush
 };
 
+static struct input_class_interface intf = {
+	.name = 	"input/event%d",
+	.mode = 	S_IFCHR | S_IRUGO | S_IWUSR,
+	.minor_base = 	EVDEV_MINOR_BASE,
+};
+
 static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct evdev *evdev;
@@ -402,8 +410,8 @@ static struct input_handle *evdev_connec
 
 	evdev_table[minor] = evdev;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
+	intf.minor = minor;
+	input_register_class_dev(dev, &intf);
 
 	return &evdev->handle;
 }

drivers/input/evdev.c static void evdev_disconnect(struct inpu · line 432

Quoted 9 lines
drivers/input/evdev.c +3 -1
@@ -417,8 +425,10 @@ static void evdev_disconnect(struct inpu
 	if (evdev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&evdev->wait);
-	} else
+	} else {
+		input_unregister_class_dev("input/event%d", evdev->minor);
 		evdev_free(evdev);
+	}
 }

You use "input/event%d" 4 times in the above code. Any way of just passing the struct input_class_interface into input_unregister_class_dev() so that you don't have to specify the name more than once anywhere?

thanks,

greg k-h

#3 lore raw
In reply to Hanna Linder

drivers/input/evdev.c static int evdev_flush(struct file * fil · line 82

Quoted 4 lines · Hanna Linder

static void evdev_free(struct evdev *evdev)
{

drivers/input/evdev.c +1 -1
-	devfs_remove("input/event%d", evdev->minor);
+	input_unregister_class_dev("input/event%d", evdev->minor);

Please don't mix up devfs and LDM stuff. devfs uses very strange devices and having them anywhere without the devfs_ prefix that should act as a big CAUTION sign is bad.

#4 lore raw
In reply to Hanna Linder

Hi!

Quoted 6 lines

I did this once before but due to some infrastructure changes it had to be written again. Here it is, pretty simple. Now you can see your input devices (except keyboard) listed under /sys/class/input like this (yes, I do have two mice attached). At the moment the dev file is created and it contains the hex value of the major and minor number.

*very* nice, and urgently needed for suspend/resume support.

But should not structure be /bus/sys/keyboard_controller/mouse0? Mouse needs to be suspended before keyboard controller...

Pavel

Signature · 2 lines
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
#5 lore raw
Quoted 10 lines · Pavel Machek

Hi!

Quoted 6 lines

I did this once before but due to some infrastructure changes it had to be written again. Here it is, pretty simple. Now you can see your input devices (except keyboard) listed under /sys/class/input like this (yes, I do have two mice attached). At the moment the dev file is created and it contains the hex value of the major and minor number.

*very* nice, and urgently needed for suspend/resume support.

No, classes have nothing to do with suspend/resume, that's devices.

Quoted 2 lines

But should not structure be /bus/sys/keyboard_controller/mouse0? Mouse needs to be suspended before keyboard controller...

Yes, but this patch is putting stuff in /sys/class/input, not /sys/bus :)

thanks,

greg k-h

#6 lore raw

Hi!

Quoted 9 lines
Quoted 8 lines
Quoted 6 lines

I did this once before but due to some infrastructure changes it had to be written again. Here it is, pretty simple. Now you can see your input devices (except keyboard) listed under /sys/class/input like this (yes, I do have two mice attached). At the moment the dev file is created and it contains the hex value of the major and minor number.

*very* nice, and urgently needed for suspend/resume support.

Quoted 7 lines

No, classes have nothing to do with suspend/resume, that's devices.

Quoted 2 lines

But should not structure be /bus/sys/keyboard_controller/mouse0? Mouse needs to be suspended before keyboard controller...

Yes, but this patch is putting stuff in /sys/class/input, not /sys/bus :)

Okay, that means that another patch is needed to create hierarchy for power managment... This sysfs stuff is getting hairy.

Pavel

Signature · 2 lines
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
#7 lore raw
Quoted 3 lines

Okay, that means that another patch is needed to create hierarchy for power managment... This sysfs stuff is getting hairy.

No it's not. The hierarchy is the device tree, which is the original purpose of it, remember?

keyboards and mice should be created as platform devices as they are probed and discovered by i8042 driver. It's not hairy, just not done yet.

-pat

#8 lore raw

Hi!

Quoted 5 lines
Quoted 2 lines

Okay, that means that another patch is needed to create hierarchy for power managment... This sysfs stuff is getting hairy.

No it's not. The hierarchy is the device tree, which is the original purpose of it, remember?

device tree is okay with me, but... it took quite a long patch to add it to classes. I thought that classes are only going to be symlinks into device tree, but this patch added classes without adding to the device tree...
Pavel

Signature · 2 lines
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
#9 lore raw
Quoted 6 lines · Pavel Machek

Hi!

Quoted 3 lines
Quoted 2 lines

Okay, that means that another patch is needed to create hierarchy for power managment... This sysfs stuff is getting hairy.

Quoted 7 lines
Quoted 2 lines

No it's not. The hierarchy is the device tree, which is the original purpose of it, remember?

device tree is okay with me, but... it took quite a long patch to add it to classes. I thought that classes are only going to be symlinks into device tree, but this patch added classes without adding to the device tree...

Al Viro has asked that sysfs conversions such as this be placed on hold until we sort through the newly-added bugs arising from the sysfsification of netdevs and request queues.

So yeah, do the work, but please make sure that you understand what went wrong with netdevs and queues, and make sure that the input sysfsification addresses those problems. Preferably in the same way...

#10 lore raw
Quoted 7 lines · Andrew Morton

Al Viro has asked that sysfs conversions such as this be placed on hold until we sort through the newly-added bugs arising from the sysfsification of netdevs and request queues.

So yeah, do the work, but please make sure that you understand what went wrong with netdevs and queues, and make sure that the input sysfsification addresses those problems. Preferably in the same way...

It doesn't - note the absense of ->release() in the introduced objects, lack of refcount in current ones and chunks like
+ class_device_unregister(&dev->class_dev);
+ kfree(dev);
in the patch. The last one is obvious breakage, no matter what else is going on - if ->class_dev is registered, it could be held by opened sysfs file and we are doing kfree() of a busy object. If it is not, unregister will be unhappy _and_ we still might have it held by opened sysfs file since the time when it used to be registered.

IOW, before something like that we'd need to make lifetime rules for evdev et.al. refcounting-based, make drivers/input/* OK with zombies ("I want it gone, but sysfs holds it") and when that is done - have freeing done from ->release() of kobject.

Note that things like evdev->open are _not_ immediately usable for refcounts - the lifetime is controlled by combination of ->exist and ->open and we do non-trivial work when current ->open hits zero, so just adding offset to ->open won't do.

#11 lore raw
Quoted 2 lines · --On Friday, June 06, 2003 12:41:50 AM +0100…

It doesn't - note the absense of ->release() in the introduced objects,

Well... The ->release() part didnt exist when I sent out this patch. I understand this original attempt had some problems.

Quoted 3 lines

zombies ("I want it gone, but sysfs holds it") and when that is done - have freeing done from ->release() of kobject.

Yup. That is the plan. I will be fully compliant in following the agreed-to sysification solution ;)

Thanks.

Hanna

#12 lore raw
In reply to Pavel Machek
Quoted 13 lines · Pavel Machek

Hi!

Quoted 10 lines
Quoted 8 lines
Quoted 6 lines

I did this once before but due to some infrastructure changes it had to be written again. Here it is, pretty simple. Now you can see your input devices (except keyboard) listed under /sys/class/input like this (yes, I do have two mice attached). At the moment the dev file is created and it contains the hex value of the major and minor number.

*very* nice, and urgently needed for suspend/resume support.

No, classes have nothing to do with suspend/resume, that's devices.

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

But should not structure be /bus/sys/keyboard_controller/mouse0? Mouse needs to be suspended before keyboard controller...

Yes, but this patch is putting stuff in /sys/class/input, not /sys/bus :)

Okay, that means that another patch is needed to create hierarchy for power managment... This sysfs stuff is getting hairy.

No, the current /sys/bus tree should be fine for showing the heirachy for power management. What in there do you feel is lacking?

greg k-h