Commit f9f852df authored by Kay Sievers's avatar Kay Sievers Committed by Greg Kroah-Hartman

Driver core: add device_type to struct device

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: default avatarKay Sievers <kay.sievers@novell.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 239378f1
...@@ -95,6 +95,8 @@ static void device_release(struct kobject * kobj) ...@@ -95,6 +95,8 @@ static void device_release(struct kobject * kobj)
if (dev->release) if (dev->release)
dev->release(dev); dev->release(dev);
else if (dev->type && dev->type->release)
dev->type->release(dev);
else if (dev->class && dev->class->dev_release) else if (dev->class && dev->class->dev_release)
dev->class->dev_release(dev); dev->class->dev_release(dev);
else { else {
...@@ -206,19 +208,25 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, ...@@ -206,19 +208,25 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
if (dev->bus && dev->bus->uevent) { if (dev->bus && dev->bus->uevent) {
/* have the bus specific function add its stuff */ /* have the bus specific function add its stuff */
retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size); retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size);
if (retval) { if (retval)
pr_debug ("%s - uevent() returned %d\n", pr_debug ("%s: bus uevent() returned %d\n",
__FUNCTION__, retval); __FUNCTION__, retval);
}
} }
if (dev->class && dev->class->dev_uevent) { if (dev->class && dev->class->dev_uevent) {
/* have the class specific function add its stuff */ /* have the class specific function add its stuff */
retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size); retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size);
if (retval) { if (retval)
pr_debug("%s - dev_uevent() returned %d\n", pr_debug("%s: class uevent() returned %d\n",
__FUNCTION__, retval); __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; return retval;
...@@ -269,37 +277,50 @@ static void device_remove_groups(struct device *dev) ...@@ -269,37 +277,50 @@ static void device_remove_groups(struct device *dev)
static int device_add_attrs(struct device *dev) static int device_add_attrs(struct device *dev)
{ {
struct class *class = dev->class; struct class *class = dev->class;
struct device_type *type = dev->type;
int error = 0; int error = 0;
int i; int i;
if (!class) if (class && class->dev_attrs) {
return 0;
if (class->dev_attrs) {
for (i = 0; attr_name(class->dev_attrs[i]); i++) { for (i = 0; attr_name(class->dev_attrs[i]); i++) {
error = device_create_file(dev, &class->dev_attrs[i]); error = device_create_file(dev, &class->dev_attrs[i]);
if (error) if (error)
break; break;
} }
if (error)
while (--i >= 0)
device_remove_file(dev, &class->dev_attrs[i]);
} }
if (error)
while (--i >= 0) if (type && type->attrs) {
device_remove_file(dev, &class->dev_attrs[i]); 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; return error;
} }
static void device_remove_attrs(struct device *dev) static void device_remove_attrs(struct device *dev)
{ {
struct class *class = dev->class; struct class *class = dev->class;
struct device_type *type = dev->type;
int i; int i;
if (!class) if (class && class->dev_attrs) {
return;
if (class->dev_attrs) {
for (i = 0; attr_name(class->dev_attrs[i]); i++) for (i = 0; attr_name(class->dev_attrs[i]); i++)
device_remove_file(dev, &class->dev_attrs[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]);
}
} }
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include <linux/hid.h> #include <linux/hid.h>
#include "usbhid.h" #include "usbhid.h"
struct device_type { struct dev_type {
u16 idVendor; u16 idVendor;
u16 idProduct; u16 idProduct;
const signed short *ff; const signed short *ff;
...@@ -48,7 +48,7 @@ static const signed short ff_joystick[] = { ...@@ -48,7 +48,7 @@ static const signed short ff_joystick[] = {
-1 -1
}; };
static const struct device_type devices[] = { static const struct dev_type devices[] = {
{ 0x046d, 0xc211, ff_rumble }, { 0x046d, 0xc211, ff_rumble },
{ 0x046d, 0xc219, ff_rumble }, { 0x046d, 0xc219, ff_rumble },
{ 0x046d, 0xc283, ff_joystick }, { 0x046d, 0xc283, ff_joystick },
......
...@@ -328,6 +328,13 @@ extern struct class_device *class_device_create(struct class *cls, ...@@ -328,6 +328,13 @@ extern struct class_device *class_device_create(struct class *cls,
__attribute__((format(printf,5,6))); __attribute__((format(printf,5,6)));
extern void class_device_destroy(struct class *cls, dev_t devt); 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 */ /* interface for exporting device attributes */
struct device_attribute { struct device_attribute {
struct attribute attr; struct attribute attr;
...@@ -356,6 +363,7 @@ struct device { ...@@ -356,6 +363,7 @@ struct device {
struct kobject kobj; struct kobject kobj;
char bus_id[BUS_ID_SIZE]; /* position on parent bus */ char bus_id[BUS_ID_SIZE]; /* position on parent bus */
struct device_type *type;
unsigned is_registered:1; unsigned is_registered:1;
struct device_attribute uevent_attr; struct device_attribute uevent_attr;
struct device_attribute *devt_attr; struct device_attribute *devt_attr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment