]> err.no Git - linux-2.6/blobdiff - drivers/input/serio/serio.c
Merge /spare/repo/linux-2.6/
[linux-2.6] / drivers / input / serio / serio.c
index b82815a0b65b60feb04bb8e7fdb46320f710d1df..edd15db17715852ff05e1119ddd02b5de248e469 100644 (file)
@@ -42,6 +42,7 @@ MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(serio_interrupt);
 EXPORT_SYMBOL(__serio_register_port);
 EXPORT_SYMBOL(serio_unregister_port);
+EXPORT_SYMBOL(serio_unregister_child_port);
 EXPORT_SYMBOL(__serio_unregister_port_delayed);
 EXPORT_SYMBOL(__serio_register_driver);
 EXPORT_SYMBOL(serio_unregister_driver);
@@ -179,12 +180,12 @@ static void serio_queue_event(void *object, struct module *owner,
        spin_lock_irqsave(&serio_event_lock, flags);
 
        /*
-        * Scan event list for the other events for the same serio port,
+        * Scan event list for the other events for the same serio port,
         * starting with the most recent one. If event is the same we
         * do not need add new one. If event is of different type we
         * need to add this event and should not look further because
         * we need to preseve sequence of distinct events.
-        */
+        */
        list_for_each_entry_reverse(event, &serio_event_list, node) {
                if (event->object == object) {
                        if (event->type == event_type)
@@ -370,7 +371,7 @@ static int serio_thread(void *nothing)
                serio_handle_events();
                wait_event_interruptible(serio_wait,
                        kthread_should_stop() || !list_empty(&serio_event_list));
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
        } while (!kthread_should_stop());
 
        printk(KERN_DEBUG "serio: kseriod exiting\n");
@@ -382,31 +383,39 @@ static int serio_thread(void *nothing)
  * Serio port operations
  */
 
-static ssize_t serio_show_description(struct device *dev, char *buf)
+static ssize_t serio_show_description(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct serio *serio = to_serio_port(dev);
        return sprintf(buf, "%s\n", serio->name);
 }
 
-static ssize_t serio_show_id_type(struct device *dev, char *buf)
+static ssize_t serio_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct serio *serio = to_serio_port(dev);
+
+       return sprintf(buf, "serio:ty%02Xpr%02Xid%02Xex%02X\n",
+                       serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
+}
+
+static ssize_t serio_show_id_type(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct serio *serio = to_serio_port(dev);
        return sprintf(buf, "%02x\n", serio->id.type);
 }
 
-static ssize_t serio_show_id_proto(struct device *dev, char *buf)
+static ssize_t serio_show_id_proto(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct serio *serio = to_serio_port(dev);
        return sprintf(buf, "%02x\n", serio->id.proto);
 }
 
-static ssize_t serio_show_id_id(struct device *dev, char *buf)
+static ssize_t serio_show_id_id(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct serio *serio = to_serio_port(dev);
        return sprintf(buf, "%02x\n", serio->id.id);
 }
 
-static ssize_t serio_show_id_extra(struct device *dev, char *buf)
+static ssize_t serio_show_id_extra(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct serio *serio = to_serio_port(dev);
        return sprintf(buf, "%02x\n", serio->id.extra);
@@ -430,7 +439,7 @@ static struct attribute_group serio_id_attr_group = {
        .attrs  = serio_device_id_attrs,
 };
 
-static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
+static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct serio *serio = to_serio_port(dev);
        struct device_driver *drv;
@@ -461,13 +470,13 @@ static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t c
        return retval;
 }
 
-static ssize_t serio_show_bind_mode(struct device *dev, char *buf)
+static ssize_t serio_show_bind_mode(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct serio *serio = to_serio_port(dev);
        return sprintf(buf, "%s\n", serio->manual_bind ? "manual" : "auto");
 }
 
-static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t count)
+static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct serio *serio = to_serio_port(dev);
        int retval;
@@ -486,6 +495,7 @@ static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t c
 
 static struct device_attribute serio_device_attrs[] = {
        __ATTR(description, S_IRUGO, serio_show_description, NULL),
+       __ATTR(modalias, S_IRUGO, serio_show_modalias, NULL),
        __ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver),
        __ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
        __ATTR_NULL
@@ -653,6 +663,19 @@ void serio_unregister_port(struct serio *serio)
        up(&serio_sem);
 }
 
+/*
+ * Safely unregisters child port if one is present.
+ */
+void serio_unregister_child_port(struct serio *serio)
+{
+       down(&serio_sem);
+       if (serio->child) {
+               serio_disconnect_port(serio->child);
+               serio_destroy_port(serio->child);
+       }
+       up(&serio_sem);
+}
+
 /*
  * Submits register request to kseriod for subsequent execution.
  * Can be used when it is not obvious whether the serio_sem is
@@ -771,36 +794,37 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv)
 
 #ifdef CONFIG_HOTPLUG
 
-#define PUT_ENVP(fmt, val)                                             \
-do {                                                                   \
-       envp[i++] = buffer;                                             \
-       length += snprintf(buffer, buffer_size - length, fmt, val);     \
-       if (buffer_size - length <= 0 || i >= num_envp)                 \
-               return -ENOMEM;                                         \
-       length++;                                                       \
-       buffer += length;                                               \
-} while (0)
+#define SERIO_ADD_HOTPLUG_VAR(fmt, val...)                             \
+       do {                                                            \
+               int err = add_hotplug_env_var(envp, num_envp, &i,       \
+                                       buffer, buffer_size, &len,      \
+                                       fmt, val);                      \
+               if (err)                                                \
+                       return err;                                     \
+       } while (0)
+
 static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
 {
        struct serio *serio;
        int i = 0;
-       int length = 0;
+       int len = 0;
 
        if (!dev)
                return -ENODEV;
 
        serio = to_serio_port(dev);
 
-       PUT_ENVP("SERIO_TYPE=%02x", serio->id.type);
-       PUT_ENVP("SERIO_PROTO=%02x", serio->id.proto);
-       PUT_ENVP("SERIO_ID=%02x", serio->id.id);
-       PUT_ENVP("SERIO_EXTRA=%02x", serio->id.extra);
-
+       SERIO_ADD_HOTPLUG_VAR("SERIO_TYPE=%02x", serio->id.type);
+       SERIO_ADD_HOTPLUG_VAR("SERIO_PROTO=%02x", serio->id.proto);
+       SERIO_ADD_HOTPLUG_VAR("SERIO_ID=%02x", serio->id.id);
+       SERIO_ADD_HOTPLUG_VAR("SERIO_EXTRA=%02x", serio->id.extra);
+       SERIO_ADD_HOTPLUG_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
+                               serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
        envp[i] = NULL;
 
        return 0;
 }
-#undef PUT_ENVP
+#undef SERIO_ADD_HOTPLUG_VAR
 
 #else