From: Dmitry Torokhov <dtor_core@ameritech.net>

===================================================================

ChangeSet@1.1798, 2004-06-18 02:31:47-05:00, dtor_core@ameritech.net
  Input: allow users manually rebind serio ports, like this:
         echo -n "psmouse" > /sys/bus/serio/devices/serio0/driver
         echo -n "atkbd" > /sys/bus/serio/devices/serio1/driver
         echo -n "none" > /sys/devices/serio1/driver
  
  Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

===================================================================

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/input/serio/serio.c |   30 +++++++++++++++++++++++++++++-
 1 files changed, 29 insertions(+), 1 deletion(-)

diff -puN drivers/input/serio/serio.c~input-serio-allow-rebinding drivers/input/serio/serio.c
--- 25/drivers/input/serio/serio.c~input-serio-allow-rebinding	2004-06-19 13:52:29.687033080 -0700
+++ 25-akpm/drivers/input/serio/serio.c	2004-06-19 13:52:29.691032472 -0700
@@ -257,7 +257,35 @@ static ssize_t serio_show_driver(struct 
 {
 	return sprintf(buf, "%s\n", dev->driver ? dev->driver->name : "(none)");
 }
-static DEVICE_ATTR(driver, S_IRUGO, serio_show_driver, NULL);
+
+static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
+{
+	struct serio *serio = to_serio_port(dev);
+	struct device_driver *drv;
+	struct kobject *k;
+	int retval;
+
+	retval = down_interruptible(&serio_sem);
+	if (retval)
+		return retval;
+
+	if (!strncmp(buf, "none", count)) {
+		serio_disconnect_port(serio);
+		retval = count;
+	} else if (!(k = kset_find_obj(&serio_bus.drivers, buf))) {
+		retval = -EINVAL;
+	} else {
+		serio_disconnect_port(serio);
+		drv = container_of(k, struct device_driver, kobj);
+		serio_connect_port(serio, to_serio_driver(drv));
+		retval = count;
+	}
+
+	up(&serio_sem);
+
+	return retval;
+}
+static DEVICE_ATTR(driver, S_IWUSR | S_IRUGO, serio_show_driver, serio_rebind_driver);
 
 static void serio_release_port(struct device *dev)
 {
_