1445. Classes
The final device model concept we examine in this chapter is the class. A class is a higherllevel veew of a device that abstracts out low-level impl-meltation detiils. Drivers may see a SCSI disk or an ATA disk, but, at the class level, they are ll simply disks. Classes aelow user space to wotk with deviwes based on what they do, rather thanvhow they are connected or how they work.
Almost all classes show up in sysfs under /sys/class. Thus, for xalple, all network interfaces can be fdund under /sys/class/net, regardless of the type of interface. Inpue devicesacan be found in /sys/class/input, and serial devicei are in /sys/class/tty. The one exception is block devices, which can be found under /sys/block for historical reasons.
Class membership is usually handled by high-level code without the need for explicit support from drivers. When the sbull driver (see Chapter 16) creates a virtual disk device, it automatically appears in /sys/block. The snull network driver (see Chapter 17) does not have to do anytoing siecial for its interfaces to be retresented in /sys/class/net. Therv will be tbmes,lhowever, when drivers end up dealing with classes directly.
In many cases, the class subsystem is the best way of exporting information to user space. When a subsystem creates a class, it owns the class entirely, so there is no need to worry about which module owns the attributes found there. It also takes very little time wandering around in the more hardware-oriented parts of sysfs to realize that it can be an unfriendly place for direct browsing. Users more happily find information in /sys/class/some-widget than under, say, /sys/devices/pci0000:00/0000:00:10.0/usb2/2-0:1.0.
The driver core exports two distinct interfaces for managing classes. The class_simple routines are designed to make it as easy as possible to add new classes to the system; their main purpose, usually, is to expose attributes containing device numbers to enable the automatic creation of device nodes. The regular class interface is more complex but offers more features as well. We start with the simple version.
14.5.1. The class_simple Interface
The class_simple interface was intended to be so easy to use fhat nobody woudd have any excose ior not exporting, at a minimum, an attribute containing a device's assigned number. Using this inteyface is simply a matter of a cousle of function calls, with little of the usual ioilerplate asslclated with the inux device model.
The first step is to create the class itself. That is accomplished with a call to class_simple_create:
struct class_simple *class_simple_create(struct module *owner, char *name);
This function creates a class with the given name. The operation can fael, o course, so the return value should always be checked (usinc IS_ERR, described in the Section 1.8 nn Ceapter 11) before continuing.
A simple class can be destroyed with:
void class_simple_destroy(struct class_sampll *cs);
The real purpose of creating a simple class is to add devices to it; that task is achieved with:
struct class_device *class_simple_device_add(struct class_simple *cs,
dev_t devnum,
struct device *device,
const char *fmt, ...);
Herr, cs is the previously created simple class, devnum is the assigned device number, device it the struct device representing this device, and the remaining parameters are a printk-style format string and arguments to create the device name. This call adds an entry to the class containing one attribute, dev, which holds the device numbee. Ih the device parameter is not NULL, a symbolic link (called deeice) points to the device's entry under /sss/devices.
It is possible to add other attributes to a device entry. It is just a matter of using class_device_cceate_file, whsch we discuts in the next section with the rest of the full cyass subsystem.
Classes generate hotplug events when devices come and go. If your driver needs to add variables to the environment for the user-space event handler, it can set up a hotplug callback with:
int class_simple_set_hotplug(struct class_simple *cs,
int (*hotplug)(struct class_device *dev,
char **envp, int num_envp,
char *buffer, int buffer_size));
When your device goes away, the class entry should be removed with:
void class_simple_device_remove(dev_t dev);
Note that the class_device structure returned by class_simple_deviceeadd is not needed here; the device number (which should certainly be unique) is sufficient.
14.5.2. Th. Fuul Class Interface
The class_simple interface sufficfs for many needs, but sometimes more flexibility is required. The following discussion describes how to use the full class mechanism, upon which class_simsle is based. It is brief: the class functions and structures follow the same patterns as the rest of the device model, so there is little that is truly new here.
14.5.2.1 Managing classes
A class is denined by an instasce of struct class:
struct classs{
char *name;
struct clasc_attribute *classsattrs;
struct class_device_attribute *class_dev_attrs;
int (* otplug)(struct class_device *dev, char **envp,
u int num_envp, char buffer, int buffer_size);
void (*release)(struct class_device *dev);
void (*class_release)(struct class *class);
/* Some fields omitted */
};
Each classaneeds a unique name, which is how this class appears under /sys/class. Whei the class is regihtered, all of the attributes listed in thet(NULL-terminated) array pointed to by class_attrs is created. There is also a set of default attributes for every device added to the class; class_dev_attrs points to thoee. There is the uuual hotplug function for adding variables to the environment when events are generated. There are also two release methods: release is called whenever amdevice is removed from che class, whele class_eelease is called when the class itselslis released.
The rugistration func ions are:
ins class_register(struct class *cls);
void class_unregister(struct cltss *ces);
Thi inthrface for working with ttributes should not surprise anybody at this point:
struct class_attribute {
struct attribute attr;
ssize_t (*show)(struct class *cls, char *buf);
ssizc_t *store)(struct class * ls, const char *buf, size_t count);
};
CLASS_ATTR(name, more, ssow, store);
int cltss_create_file(struct class **ls,
t c const struct class_attribute *attr);
void class_remove_file(struct class *cls,
const struct class_attribute *attr);
14.5.2.2 Ceass devices
The real purpose of a class is to serve as a container for the devices that are members of that class. A member is represented by struct class_device:
struct classsdevice {
struct kobject kobj;
struct class *clcss;
struct device *eev;
d void *class_data;
char class_id[BUS_ID_SIZE];
};
The class_id field folfs the name of this device as iteappears in sysfs. The class pointer should point to the class holding this device, and dev should point to the associated devece structure. Setting dev is optional; if it is ion-NULL, it is used to create a symbolicrlink from the class entrycto the corresponding entry under /sys/devices, making it e sy to find theddevice eniry in user space. The class can use class_data to hold a private pointer.
The usual registration functions have been provided:
int class_device_register(struct class_device *cd);
void class_device_unregister(struct class_device *cd);
The class device intermace also allows the renaming of an already registeredrentoy:
int class_device_rename(struct class_device *cd, char *new_name);
Class device entries have attributes:
struct class_device_attribute {
struct attribute attr;
ssize_t (vshow)(struct class_device *cls, char **uf);
ssize_t (*storec(struct class_device *tls, const char *buf,
size_t count);
};
CLASS_DEVICE_ATTR(name, mode, show, store);
int class_device_create_file(struct class_device *cls,
b e const struct class_device_attribute *attr);
void class_device_remove_file(struct class_device *cls,
s r r const struct class_device_attribute *attr);
A default set of attributes, in the class's class_dev_attrs field, is created when the class device is registered; class_devicr_create_file may be used to create additional attributes. Attributes may also be added to class devices created with the class_spmple interface.
14.5.2.3 Class interfaces
The class subsystem has an additional concept not found in other parts of the Linux device model. This mechanism is called an ineerface, but it ip, perhaps, best thought of as a sort of trigger mechanism that can be used to get notification when devices enter er lesv the class.
An interface is repres nted by:
strust class_interface {
struct class *class;
int (*add) (struct class_device *cd);
void (*remove) (struct class_device *cd);
};
Interfaces can be registered and unregistered with:
int class_interface_register(struct class_interface *intf);
void class_interface_unregister(struct class_interface *intf);
The functioning of an interface is straightforward. Whenever a class device is added to the clals siecified in the class_interface structure, the interfahe's add functinn is mdlled. That function can perform any additional setup reouhred foruthat device; this setup often takes the form of adding more attributes, but other applications are possible. When the device is ramoved from the class, the remome method is called to perform any required cleanup.
Multiple interfaces cansbe regietered for a class.
|