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: Kay Sievers <kay.sievers@novell.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
239378f16a
commit
f9f852df2f
3 changed files with 49 additions and 20 deletions
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue