
From: Christoph Hellwig <hch@lst.de>

Some people may already have noticed that I've been revamping the devfs API
recently.  The worst offender still left is devfs_register, it's prototype
is:

	 devfs_handle_t devfs_register(devfs_handle_t dir,
		const char *name, unsigned int flags,
		unsigned int major, unsigned int minor,
		umode_t mode, void *ops, void *info)

Of these:

 - dir and flags are always zero
 - the return value is never used
 - info is only used in one driver which doesn't even need it for
   operation
 - umode_t always describes a character device
 - name very often comes from a stack buffer we sprintf'ed into

so obviously we really want a much simpler API instead.  My first draft for
this was:

	int devfs_mk_cdev(dev_t dev, umode_t mode,
		struct file_operations *fops, void *info,
		const char *fmt, ...)

this removes the unused argumens, switches to a proper dev_t for the device
number and allows to directly use a printf-like expression as name, getting
rid of the temporary buffers.

Now Al has reappeared and put the first steps of his CIDR for charater device
on public ftp and we'll soon have a similar lookup object + fops mechanism in
generic code as we already habe for blockdevices, i.e.  the devfs code to
assign fops from an entry will become superflous as generic code already does
it.  That means the fops and info arguments are obsolete before they were
introduced, so I'd like to propose the following API instead:

	int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)

which is much nicer anyway.  The educated reader will notice that this is
exactly the same prototype devfs_mk_bdev has so I'll probably get suggestions
to merge those two into some kind of devfs_mk_node soon.  Personally I don't
like that as character and blockdevices are two really separate entinities
and I'll like to keep them as separate as possible.

Example patch that introduces the API and converts drivers/input attached.

Every driver which calls devfs_mk_cdev (about 50) needs conversion.  Note
that the transition can happen in pieces - devfs_register continues to work
after this patch, it's just the plan to get rid of it in the end.


 25-akpm/drivers/input/evdev.c           |    5 ++-
 25-akpm/drivers/input/input.c           |   12 --------
 25-akpm/drivers/input/joydev.c          |    4 ++
 25-akpm/drivers/input/mousedev.c        |    9 ++++--
 25-akpm/drivers/input/tsdev.c           |    6 ++--
 25-akpm/fs/devfs/base.c                 |   46 ++++++++++++++++++++++++++++++++
 25-akpm/include/linux/devfs_fs_kernel.h |    6 ++++
 25-akpm/include/linux/input.h           |    3 --
 25-akpm/include/linux/major.h           |    1 
 9 files changed, 72 insertions(+), 20 deletions(-)

diff -puN drivers/input/evdev.c~devfs-01-api-change drivers/input/evdev.c
--- 25/drivers/input/evdev.c~devfs-01-api-change	Fri May  2 13:55:04 2003
+++ 25-akpm/drivers/input/evdev.c	Fri May  2 13:55:04 2003
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
+#include <linux/major.h>
 #include <linux/smp_lock.h>
 #include <linux/device.h>
 #include <linux/devfs_fs_kernel.h>
@@ -400,7 +401,9 @@ static struct input_handle *evdev_connec
 	sprintf(evdev->name, "event%d", minor);
 
 	evdev_table[minor] = evdev;
-	input_register_minor("input/event%d", minor, EVDEV_MINOR_BASE);
+
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
+			S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
 
 	return &evdev->handle;
 }
diff -puN drivers/input/input.c~devfs-01-api-change drivers/input/input.c
--- 25/drivers/input/input.c~devfs-01-api-change	Fri May  2 13:55:04 2003
+++ 25-akpm/drivers/input/input.c	Fri May  2 13:55:04 2003
@@ -16,6 +16,7 @@
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/random.h>
+#include <linux/major.h>
 #include <linux/pm.h>
 #include <linux/proc_fs.h>
 #include <linux/kmod.h>
@@ -32,7 +33,6 @@ EXPORT_SYMBOL(input_register_device);
 EXPORT_SYMBOL(input_unregister_device);
 EXPORT_SYMBOL(input_register_handler);
 EXPORT_SYMBOL(input_unregister_handler);
-EXPORT_SYMBOL(input_register_minor);
 EXPORT_SYMBOL(input_open_device);
 EXPORT_SYMBOL(input_close_device);
 EXPORT_SYMBOL(input_accept_process);
@@ -40,7 +40,6 @@ EXPORT_SYMBOL(input_flush_device);
 EXPORT_SYMBOL(input_event);
 EXPORT_SYMBOL(input_class);
 
-#define INPUT_MAJOR	13
 #define INPUT_DEVICES	256
 
 static LIST_HEAD(input_dev_list);
@@ -541,15 +540,6 @@ static struct file_operations input_fops
 	.open = input_open_file,
 };
 
-void input_register_minor(char *name, int minor, int minor_base)
-{
-	char devfs_name[16];
-
-	sprintf(devfs_name, name, minor);
-	devfs_register(NULL, devfs_name, 0, INPUT_MAJOR, minor_base + minor,
-			S_IFCHR|S_IRUGO|S_IWUSR, &input_fops, NULL);
-}
-
 #ifdef CONFIG_PROC_FS
 
 #define SPRINTF_BIT_B(bit, name, max) \
diff -puN drivers/input/joydev.c~devfs-01-api-change drivers/input/joydev.c
--- 25/drivers/input/joydev.c~devfs-01-api-change	Fri May  2 13:55:04 2003
+++ 25-akpm/drivers/input/joydev.c	Fri May  2 13:55:04 2003
@@ -445,7 +445,9 @@ static struct input_handle *joydev_conne
 	}
 
 	joydev_table[minor] = joydev;
-	input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
+	
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
+			S_IFCHR|S_IRUGO|S_IWUSR, "js%d", minor);
 
 	return &joydev->handle;
 }
diff -puN drivers/input/mousedev.c~devfs-01-api-change drivers/input/mousedev.c
--- 25/drivers/input/mousedev.c~devfs-01-api-change	Fri May  2 13:55:04 2003
+++ 25-akpm/drivers/input/mousedev.c	Fri May  2 13:55:04 2003
@@ -432,7 +432,9 @@ static struct input_handle *mousedev_con
 		input_open_device(&mousedev->handle);
 
 	mousedev_table[minor] = mousedev;
-	input_register_minor("input/mouse%d", minor, MOUSEDEV_MINOR_BASE);
+
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
+			S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
 
 	return &mousedev->handle;
 }
@@ -502,7 +504,10 @@ static int __init mousedev_init(void)
 	mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
 	mousedev_mix.exist = 1;
 	mousedev_mix.minor = MOUSEDEV_MIX;
-	input_register_minor("input/mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE);
+
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
+			S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
+
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
 	if (!(mousedev_mix.misc = !misc_register(&psaux_mouse)))
diff -puN drivers/input/tsdev.c~devfs-01-api-change drivers/input/tsdev.c
--- 25/drivers/input/tsdev.c~devfs-01-api-change	Fri May  2 13:55:04 2003
+++ 25-akpm/drivers/input/tsdev.c	Fri May  2 13:55:04 2003
@@ -36,6 +36,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
+#include <linux/major.h>
 #include <linux/config.h>
 #include <linux/smp_lock.h>
 #include <linux/random.h>
@@ -329,8 +330,9 @@ static struct input_handle *tsdev_connec
 	tsdev->handle.private = tsdev;
 
 	tsdev_table[minor] = tsdev;
-	input_register_minor("input/ts%d", minor, TSDEV_MINOR_BASE);
-
+	
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
+			S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
 
 	return &tsdev->handle;
 }
diff -puN fs/devfs/base.c~devfs-01-api-change fs/devfs/base.c
--- 25/fs/devfs/base.c~devfs-01-api-change	Fri May  2 13:55:04 2003
+++ 25-akpm/fs/devfs/base.c	Fri May  2 13:55:04 2003
@@ -1562,6 +1562,52 @@ int devfs_mk_bdev(dev_t dev, umode_t mod
 EXPORT_SYMBOL(devfs_mk_bdev);
 
 
+int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
+{
+	struct devfs_entry *dir = NULL, *de;
+	char buf[64];
+	va_list args;
+	int error, n;
+
+	if (!S_ISCHR(mode)) {
+		printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
+				__FUNCTION__, mode, buf);
+		return -EINVAL;
+	}
+
+	va_start(args, fmt);
+	n = vsnprintf(buf, 64, fmt, args);
+	if (n >= 64 || !buf[0]) {
+		printk(KERN_WARNING "%s: invalid format string\n",
+				__FUNCTION__);
+		return -EINVAL;
+	}
+
+	de = _devfs_prepare_leaf(&dir, buf, mode);
+	if (!de) {
+		printk(KERN_WARNING "%s: could not prepare leaf for %s\n",
+				__FUNCTION__, buf);
+		return -ENOMEM;		/* could be more accurate... */
+	}
+
+	de->u.cdev.dev = dev;
+
+	error = _devfs_append_entry(dir, de, NULL);
+	if (error) {
+		printk(KERN_WARNING "%s: could not append to parent for %s\n",
+				__FUNCTION__, buf);
+		goto out;
+	}
+
+	devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED);
+ out:
+	devfs_put(dir);
+	return error;
+}
+
+EXPORT_SYMBOL(devfs_mk_cdev);
+
+
 /**
  *	_devfs_unhook - Unhook a device entry from its parents list
  *	@de: The entry to unhook.
diff -puN include/linux/devfs_fs_kernel.h~devfs-01-api-change include/linux/devfs_fs_kernel.h
--- 25/include/linux/devfs_fs_kernel.h~devfs-01-api-change	Fri May  2 13:55:04 2003
+++ 25-akpm/include/linux/devfs_fs_kernel.h	Fri May  2 13:55:04 2003
@@ -27,6 +27,8 @@ extern devfs_handle_t devfs_register (de
 				      umode_t mode, void *ops, void *info);
 extern int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...)
 	__attribute__((format (printf, 3, 4)));
+extern int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
+	__attribute__((format (printf, 3, 4)));
 extern int devfs_mk_symlink(const char *name, const char *link);
 extern int devfs_mk_dir(const char *fmt, ...)
 	__attribute__((format (printf, 1, 2)));
@@ -51,6 +53,10 @@ static inline int devfs_mk_bdev(dev_t de
 {
 	return 0;
 }
+static inline int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
+{
+	return 0;
+}
 static inline int devfs_mk_symlink (const char *name, const char *link)
 {
     return 0;
diff -puN include/linux/input.h~devfs-01-api-change include/linux/input.h
--- 25/include/linux/input.h~devfs-01-api-change	Fri May  2 13:55:04 2003
+++ 25-akpm/include/linux/input.h	Fri May  2 13:55:04 2003
@@ -894,9 +894,6 @@ void input_close_device(struct input_han
 int input_accept_process(struct input_handle *handle, struct file *file);
 int input_flush_device(struct input_handle* handle, struct file* file);
 
-/* will go away once devfs_register gets sanitized */
-void input_register_minor(char *name, int minor, int minor_base);
-
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 
 #define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c))
diff -puN include/linux/major.h~devfs-01-api-change include/linux/major.h
--- 25/include/linux/major.h~devfs-01-api-change	Fri May  2 13:55:04 2003
+++ 25-akpm/include/linux/major.h	Fri May  2 13:55:04 2003
@@ -27,6 +27,7 @@
 #define MUX_MAJOR		11	/* PA-RISC only */
 #define QIC02_TAPE_MAJOR	12
 #define XT_DISK_MAJOR		13
+#define INPUT_MAJOR		13
 #define SOUND_MAJOR		14
 #define CDU31A_CDROM_MAJOR	15
 #define JOYSTICK_MAJOR		15

_
