Device Model of Linux Driver (6)-driver

Source: Internet
Author: User

1. Device Driver. In the Linux device model, the device driver is represented by the device_driver structure.

Struct device_driver {const char * Name;/* name */struct bus_type * bus;/* attached bus */struct module * owner; const struct of_device_id * of_match_table; INT (* probe) (struct device * Dev);/* call */INT (* remove) (struct device * Dev) when the device matches the driver ); /* call */void (* shutdown) (struct device * Dev) when the device is removed; int (* suspend) (struct device * Dev, pm_message_t State); int (* resume) (struct device * Dev); const struct attribute_group ** groups;/* Attribute Group * // * power management operation */const struct dev_pm_ops * PM; struct driver_private * P; /* private data: Embedded kobject, device linked list, and bus linked list node */};

2. Declare and initialize the driver structure

The driver struct is declared static. At least name and bus members must be initialized. Generally, the device_driver struct is not directly used, but is encapsulated by a struct. The following is an example of the eepro100 driver struct declaration:

/* New encapsulated driver struct */struct pci_driver {const struct pci_device_id * id_table; struct device_driver driver;};/* declare the driver struct */static struct pci_driver eepro100_driver = {. id_table = eepro100_pci_tbl ,. driver = {. name = "eepro100 ",. bus = & pci_bus_type ,. probe = eepro100_probe ,. remove = eepro100_remove ,. suspend = eepro100_suspend ,. resume = eepro100_resume ,},};

3. Registration and logout drivers

Registration driver

Int driver_register (struct device_driver * DRV );

Cancel driver

Void driver_unregister (struct device_driver * DRV );

Register driver function analysis:

Int driver_register (struct device_driver * DRV) {int ret; struct device_driver * Other;/* If the private data P pointer is null, oops */bug_on (! DRV-> bus-> P);/* check whether probe, remove, shutdown callback */If (DRV-> bus-> probe & DRV-> probe) is implemented) | (DRV-> bus-> remove & DRV-> remove) | (DRV-> bus-> shutdown & DRV-> shutdown )) printk (kern_warning "Driver '% s' needs updating-Please use" "bus_type Methods \ n", DRV-> name ); /* check whether the driver has been registered on the bus */Other = driver_find (DRV-> name, DRV-> Bus); If (other) {put_driver (other ); printk (kern_err "error: Driver '% s' is alre Ady registered, "" aborting... \ n ", DRV-> name); Return-ebusy;}/* register the driver with the bus */ret = bus_add_driver (DRV); If (RET) return ret; /* Create an attribute file */ret = driver_add_groups (DRV, DRV-> groups); If (RET) bus_remove_driver (DRV); return ret;} int bus_add_driver (struct device_driver * DRV) {struct bus_type * bus; struct driver_private * priv; int error = 0;/* Reference count of bus plus 1 */bus = bus_get (DRV-> Bus); If (! Bus) Return-einval; priv = kzarloc (sizeof (* priv), gfp_kernel); If (! Priv) {error =-enomem; goto out_put_bus;} klist_init (& priv-> klist_devices, null, null); priv-> driver = DRV; DRV-> P = priv; priv-> kobj. kset = bus-> P-> drivers_kset;/* initialize and add kobject */error = kobject_init_and_add (& priv-> kobj, & driver_ktype, null, "% s ", DRV-> name); If (error) goto out_unregister;/* If Automatic Probe is set, driver_attach */If (DRV-> bus-> P-> drivers_autoprobe) is called) {error = driver_attach (DRV); If (error) GOTO Out_unregister;}/* List of drivers added to the bus */klist_add_tail (& priv-> knode_bus, & bus-> P-> klist_drivers ); module_add_driver (DRV-> owner, DRV);/* Create a driver attribute file */error = driver_create_file (DRV, & driver_attr_uevent); If (error) {printk (kern_err "% s: uevent ATTR (% s) failed \ n ",__ func __, DRV-> name);} error = driver_add_attrs (bus, DRV); If (error) {/* how the hell do we get out of this pickle? Give up */printk (kern_err "% s: driver_add_attrs (% s) failed \ n" ,__ func __, DRV-> name);} If (! DRV-> suppress_bind_attrs) {error = add_bind_files (DRV); If (error) {/* ditto */printk (kern_err "% s: add_bind_files (% s) failed \ n ", __func __, DRV-> name) ;}}/* Send kobj_add uevent */kobject_uevent (& priv-> kobj, kobj_add) to the user space; return 0 ;}

Driver_attach ()-> bus_for_each_dev () traverses all the devices on the bus and calls _ driver_attach () for each device to bind the driver to the device.

Static int _ driver_attach (struct device * Dev, void * Data) {struct device_driver * DRV = data;/* driver and device match */If (! Driver_match_device (DRV, Dev) return 0; If (Dev-> parent)/* needed for USB */device_lock (Dev-> parent); device_lock (Dev); If (! Dev-> driver)/* Call probe */driver_probe_device (DRV, Dev); device_unlock (Dev); If (Dev-> parent) device_unlock (Dev-> parent ); return 0 ;}

When a driver supports a device, call the _ driver_attach function to complete the corresponding work. _ driver_attach ()-> driver_probe_device ()-> bus-> probe () -> DRV-> probe () first calls the probe function defined in the bus. If probe is not defined in the bus, then the probe defined in the driver is called.

4. Driver attributes, which are described by driver_attribute

struct driver_attribute {         struct attribute attr;         ssize_t (*show)(struct device_driver*driver, char *buf);         ssize_t (*store)(struct device_driver*driver, const char *buf,                             size_t count);};DRIVER_ATTR(_name,_mode, _show, _store)

Create attributes

Intdriver_create_file (struct device_driver * driver,

Const structdriver_attribute * ATTR );

Delete attributes

Voiddriver_remove_file (struct device_driver * driver,

Const struct driver_attribute * ATTR );

 

7.4 instance analysis

/** For learn driver */# include <Linux/kernel. h> # include <Linux/module. h> # include <Linux/init. h> # include <Linux/device. h> # include <Linux/string. h> extern struct bus_type scbus_type; static char * version = "revision 1.0, scdriver"; static int SC _probe (struct device * Dev) {printk ("driverfound device \ n "); return0;} static int SC _remove (struct device * Dev) {printk ("deviceremove \ n"); return0;} struct device_driver scdriver = {. name = "scdevice0",/* driver name, used to match supported devices */. bus = & scbus_type,/* type of the attached bus */. probe = SC _probe,/* call when the device matches the driver */. remove = SC _remove,/* called when the device is removed */};/** export driver attribute */static ssize_t driver_show_version (structdevice_driver * driver, char * BUF) {returnsprintf (BUF, "% s \ n", version);} static driver_attr (version, s_irugo, driver_show_version, null); static int _ init scdriver_init (void) {intret; /* register the driver */ret = driver_register (& scdriver); If (RET) returnret;/* Create attributes */ret = driver_create_file (& scdriver, & driver_attr_version ); if (RET) gotoerr_create; printk ("drvierregistered \ n"); return0; err_create: driver_unregister (& scdriver); returnret;} static void _ exit scdriver_exit (void) {modules (& scdriver, & drivers); driver_unregister (& scdriver);} module_init (scdriver_init); module_exit (scdriver_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.