Driver core: add device_type to struct device
authorKay Sievers <kay.sievers@novell.com>
Sat, 7 Oct 2006 19:54:55 +0000 (21:54 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 7 Feb 2007 18:37:14 +0000 (10:37 -0800)
This allows us to add type specific attributes, uevent vars and
release funtions.

A subsystem can carry different types of devices like the "block"
subsys has disks and partitions. Both types create a different set
of attributes, but belong to the same subsystem.

This corresponds to the low level objects:
  kobject   -> device       (object/device data)
  kobj_type -> device_type  (type of object/device we are embedded in)
  kset      -> class/bus    (list of objects/devices of a subsystem)

Signed-off-by: Kay Sievers <kay.sievers@novell.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/base/core.c
drivers/usb/input/hid-lgff.c
include/linux/device.h

index 7a5336f7df897605f576f6bcd28f1e0f153fff7b..34ac18778d8a30173a2eecef077cd04c819527c3 100644 (file)
@@ -95,6 +95,8 @@ static void device_release(struct kobject * kobj)
 
        if (dev->release)
                dev->release(dev);
+       else if (dev->type && dev->type->release)
+               dev->type->release(dev);
        else if (dev->class && dev->class->dev_release)
                dev->class->dev_release(dev);
        else {
@@ -206,19 +208,25 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
        if (dev->bus && dev->bus->uevent) {
                /* have the bus specific function add its stuff */
                retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size);
-                       if (retval) {
-                       pr_debug ("%s - uevent() returned %d\n",
+               if (retval)
+                       pr_debug ("%s: bus uevent() returned %d\n",
                                  __FUNCTION__, retval);
-               }
        }
 
        if (dev->class && dev->class->dev_uevent) {
                /* have the class specific function add its stuff */
                retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size);
-                       if (retval) {
-                               pr_debug("%s - dev_uevent() returned %d\n",
-                                        __FUNCTION__, retval);
-               }
+               if (retval)
+                       pr_debug("%s: class uevent() returned %d\n",
+                                __FUNCTION__, retval);
+       }
+
+       if (dev->type && dev->type->uevent) {
+               /* have the device type specific fuction add its stuff */
+               retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size);
+               if (retval)
+                       pr_debug("%s: dev_type uevent() returned %d\n",
+                                __FUNCTION__, retval);
        }
 
        return retval;
@@ -269,37 +277,50 @@ static void device_remove_groups(struct device *dev)
 static int device_add_attrs(struct device *dev)
 {
        struct class *class = dev->class;
+       struct device_type *type = dev->type;
        int error = 0;
        int i;
 
-       if (!class)
-               return 0;
-
-       if (class->dev_attrs) {
+       if (class && class->dev_attrs) {
                for (i = 0; attr_name(class->dev_attrs[i]); i++) {
                        error = device_create_file(dev, &class->dev_attrs[i]);
                        if (error)
                                break;
                }
+               if (error)
+                       while (--i >= 0)
+                               device_remove_file(dev, &class->dev_attrs[i]);
        }
-       if (error)
-               while (--i >= 0)
-                       device_remove_file(dev, &class->dev_attrs[i]);
+
+       if (type && type->attrs) {
+               for (i = 0; attr_name(type->attrs[i]); i++) {
+                       error = device_create_file(dev, &type->attrs[i]);
+                       if (error)
+                               break;
+               }
+               if (error)
+                       while (--i >= 0)
+                               device_remove_file(dev, &type->attrs[i]);
+       }
+
        return error;
 }
 
 static void device_remove_attrs(struct device *dev)
 {
        struct class *class = dev->class;
+       struct device_type *type = dev->type;
        int i;
 
-       if (!class)
-               return;
-
-       if (class->dev_attrs) {
+       if (class && class->dev_attrs) {
                for (i = 0; attr_name(class->dev_attrs[i]); i++)
                        device_remove_file(dev, &class->dev_attrs[i]);
        }
+
+       if (type && type->attrs) {
+               for (i = 0; attr_name(type->attrs[i]); i++)
+                       device_remove_file(dev, &type->attrs[i]);
+       }
 }
 
 
index e47466268565668d10285c3948f5acbc3b49a3ba..4f4fc3be192e9116f40128b03b12384dbd06e124 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/hid.h>
 #include "usbhid.h"
 
-struct device_type {
+struct dev_type {
        u16 idVendor;
        u16 idProduct;
        const signed short *ff;
@@ -48,7 +48,7 @@ static const signed short ff_joystick[] = {
        -1
 };
 
-static const struct device_type devices[] = {
+static const struct dev_type devices[] = {
        { 0x046d, 0xc211, ff_rumble },
        { 0x046d, 0xc219, ff_rumble },
        { 0x046d, 0xc283, ff_joystick },
index da7221913114ce31488fdeae8b7e81cba10f4299..e1e164f81eea3b5168d2310cb66deafb20fc9d08 100644 (file)
@@ -328,6 +328,13 @@ extern struct class_device *class_device_create(struct class *cls,
                                        __attribute__((format(printf,5,6)));
 extern void class_device_destroy(struct class *cls, dev_t devt);
 
+struct device_type {
+       struct device_attribute *attrs;
+       int (*uevent)(struct device *dev, char **envp, int num_envp,
+                     char *buffer, int buffer_size);
+       void (*release)(struct device *dev);
+};
+
 /* interface for exporting device attributes */
 struct device_attribute {
        struct attribute        attr;
@@ -356,6 +363,7 @@ struct device {
 
        struct kobject kobj;
        char    bus_id[BUS_ID_SIZE];    /* position on parent bus */
+       struct device_type      *type;
        unsigned                is_registered:1;
        struct device_attribute uevent_attr;
        struct device_attribute *devt_attr;