Device Model of Linux Driver (5)-Device

Source: Internet
Author: User

1. device. The device structure is used to describe the device in LDM.

Struct device {/* parent device, usually a bus or host device */struct device * parent;/* Private Data Pointer: Sub-device linked list, parent device linked list node, driver linked list node, bus linked list node */struct device_private * P; struct kobject kobj;/* connect to the kobject */const char * init_name in the structure system; /* initial name of the device */const struct device_type * type;/* device type */struct bus_type * bus;/* attached bus */struct device_driver * driver; /* associated driver */void * platform_data;/* platform specific data */dev_t devt;/* dev_t, creates the sysfs "Dev" */struct klist_node knode_class; /**/struct class * class;/* class of the device */const struct attribute_group ** groups;/* optional groups */void (* release) (structdevice * Dev);/* call when the reference count (kobject-> kref) is reduced to 0 */};

When registering a device, we usually need to initialize the parent, name, bus_id, and bus members.

2. registration and cancellation of devices

    int device_register(struct device *dev)    void device_unregister(struct device *dev)

Register function analysis. The register function is divided into two parts: device_initialize and device_add.

Int device_add (structdevice * Dev) {struct device * parent = NULL; struct class_interface * class_intf; int error =-einval; /* Add 1 */Dev = get_device (Dev);/** for Statically allocated devices, whichshoshould all be converted * some day, We need to initialize the name. we prevent reading back * the name, and force the use of dev_name () */If (Dev-> init_name) {dev_set_name (Dev, "% s ", dev-> init_name); Dev-> init_name = NULL;}/* increase the reference count of the parent device */parent = get_device (Dev-> parent); setup_parent (Dev, parent);/* register the embedded kobject to the device model */error = kobject_add (& Dev-> kobj, Dev-> kobj. parent, null);/* Create the property file uevent */error = device_create_file (Dev, & uevent_attr);/* If devt is defined, the Dev attribute */If (Major (Dev-> devt) {error = device_create_file (Dev, & devt_attr);} is generated );} /* Create an attribute file */error = device_add_class_symlinks (Dev); error = device_add_attrs (Dev);/* Add the device to the bus. This is the key, analyze it later */error = bus_add_device (Dev);/* generate kobj_add uevent */kobject_uevent (& Dev-> kobj, kobj_add ); /* test the corresponding driver for the device */bus_probe_device (Dev);/* If the device has a parent device, add it to the sub-device chain of the parent */If (parent) klist_add_tail (& Dev-> P-> knode_parent, & parent-> P-> klist_children);/* if the device is attached to a class, then you need to complete the corresponding work */If (Dev-> class) {/* Add the device to the device linked list of the class to complete the Association */klist_add_tail (& Dev-> knode_class, & Dev-> class-> P-> klist_devices);/* policy any interfaces thatthe device is here */list_for_each_entry (class_intf, & Dev-> class-> P-> class_interfaces, node) if (class_intf-> add_dev) class_intf-> add_dev (Dev, class_intf );}}

Bus_add_device ()

Int bus_add_device (struct device * Dev) {/* Reference count plus one */struct bus_type * bus = bus_get (Dev-> Bus); If (bus) {/* Create an attribute file */error = device_add_attrs (bus, Dev); error = sysfs_create_link (& bus-> P-> devices_kset-> kobj, & Dev-> kobj, dev_name (Dev); error = sysfs_create_link (& Dev-> kobj, & Dev-> bus-> P-> subsys. kobj, "subsystem");/* Add the device to the device chain of the bus. This step focuses on */klist_add_tail (& Dev-> P-> knode_bus, & bus-> P-> klist_devices );}}

Bus_probe_device ()-> device_attach ()

Int device_attach (struct device * Dev) {If (Dev-> driver) {/* if the device is already attached to a driver, bind it */ret = device_bind_driver (Dev );} else {/* traverse bus-> P-> klist_drivers to find the matching driver, and then execute the callback function _ device_attach */ret = bus_for_each_drv (Dev-> bus, null, Dev, __device_attach);} out_unlock: device_unlock (Dev); return ret ;}

_ Device_attach ()-> driver_probe_device ()-> really_probe ()-> bus-> probe ()-> DRV-> probe () the probe function defined in the bus is executed first. If no probe is defined in the bus, the probe function defined in the driver is executed.

3. device Properties

The device property is represented by device_attribute.

Structdevice_attribute {struct attribute ATTR;/* attribute */ssize_t (* Show) (struct device * Dev, struct device_attribute * ATTR, char * BUF ); /* read attributes */ssize_t (* store) (struct device * Dev, struct device_attribute * ATTR, const char * Buf, size_t count);/* write attributes */};

Initialize device properties:

DEVICE_ATTR(_name,_mode, _show, _store)

Generate and remove attribute files under the sysfs directory

int device_create_file(struct device *device,                                               conststruct device_attribute *entry);void device_remove_file(struct device *dev,                                                const struct device_attribute*attr);

 

4. instance resolution

Create a Device and Its Property version, and mount the device to the previously created bus.

/** For learn device */# include <Linux/init. h> # include <Linux/module. h> # include <Linux/kernel. h> # include <Linux/device. h> extern struct bus_type scbus_type; extern struct device scbus; static char * version = "revision1.0";/* destructor, when the reference count is reduced to 0, call */void screlease (struct device * Dev) {printk ("scbusrelease \ n");} struct device scdevice = {. parent = & scbus,/* parent device, which is the attached bus */. init_name = "scdevice0 ",. bus = & scbus_type,/* type of the attached bus */. release = screlease,};/** export device attribute */static ssize_t show_device_version (structdevice * Dev, structdevice_attribute * ATTR, char * BUF) {returnsprintf (BUF, "% s \ n", version);} device_attr (version, 0666, show_device_version, null); static int _ init scdevice_init (void) {intret; /* register the device */ret = device_register (& scdevice); If (RET) returnret;/* create Attribute */ret = device_create_file (& scdevice, & dev_attr_version ); if (RET) gotoerr_create; printk ("createa scdevice"); return0; err_create: device_unregister (& scdevice); returnret;} static void _ exit scdevice_exit (void) {device_remove_file (& scdevice, & dev_attr_version); device_unregister (& scdevice); printk ("removea scdevice");} module_init (scdevice_init); module_exit (scdevice_exit ); module_license ("dual BSD/GPL"); module_author ("cjok <cjok.liao@gmail.com> ");

Test results:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.