platform总线的匹配方式( 二 )


第 7 行,成员,为结构体变量,Linux 内核里面大量使用到了面向对象
的思维,相当于基类,提供了最基础的驱动框架 。继承了这个基类,
然后在此基础上又添加了一些特有的成员变量 。
1 struct device_driver {2 const char *name;3 struct bus_type *bus;4 5 struct module *owner;6 const char *mod_name; /* used for built-in modules */7 8 bool suppress_bind_attrs; /* disables bind/unbind via sysfs */9 10 const struct of_device_id *of_match_table;11 const struct acpi_device_id *acpi_match_table;1213 int (*probe) (struct device *dev);14 int (*remove) (struct device *dev);15 void (*shutdown) (struct device *dev);16 int (*suspend) (struct device *dev, pm_message_t state);17 int (*resume) (struct device *dev);18 const struct attribute_group **groups;1920 const struct dev_pm_ops *pm;2122 struct driver_private *p;23 };

platform总线的匹配方式

文章插图
第 10 行,就是采用设备树的时候驱动使用的匹配表,同样是数组,每个匹配项都为结构体类型
1 struct of_device_id {2 char name[32];3 char type[32];4 char compatible[128];5 const void *data;6 };
编写 驱动的时候,1.首先定义一个结构体变量,2.然后实现结构体中的各个成员变量,重点是实现匹配方法以及 probe 函数 。3.需要在驱动入口函数里面调用
ster 函数向 Linux 内核注册一个驱动 。
int ster (*)
void (*drv)
示例:
1 struct xxx_dev{2struct cdev cdev;3 /* 设备结构体其他具体内容 */4 };5 6 struct xxx_dev xxxdev; /* 定义个设备结构体变量 */7 8 static int xxx_open(struct inode *inode, struct file *filp)9 { 10/* 函数具体内容 */11return 0;12 }1314 static ssize_t xxx_write(struct file *filp, const char __user *buf,size_t cnt, loff_t *offt)15 {16/* 函数具体内容 */17return 0;18 }1920 /*21 * 字符设备驱动操作集22 */23 static struct file_operations xxx_fops = {24.owner = THIS_MODULE,25.open = xxx_open,26.write = xxx_write,27 };2829 /*30 * platform 驱动的 probe 函数31 * 驱动与设备匹配成功以后此函数就会执行32 */33 static int xxx_probe(struct platform_device *dev)34 { 35......36cdev_init(&xxxdev.cdev, &xxx_fops); /* 注册字符设备驱动 */37/* 函数具体内容 */38return 0;39 }4041 static int xxx_remove(struct platform_device *dev)42 {43......44cdev_del(&xxxdev.cdev);/* 删除 cdev */45/* 函数具体内容 */46return 0;47 }4849 /* 匹配列表 */50 static const struct of_device_id xxx_of_match[] = {51{ .compatible = "xxx-gpio" },52{ /* Sentinel */ }53 };5455 /* 56 * platform 平台驱动结构体57 */58 static struct platform_driver xxx_driver = {59.driver = {60.name = "xxx",61.of_match_table = xxx_of_match,62 },63.probe = xxx_probe,64.remove = xxx_remove,65 };66 67 /* 驱动模块加载 */68 static int __init xxxdriver_init(void)69 {70return platform_driver_register(&xxx_driver);71 }7273 /* 驱动模块卸载 */74 static void __exit xxxdriver_exit(void)75 {76platform_driver_unregister(&xxx_driver);77 }7879 module_init(xxxdriver_init);80 module_exit(xxxdriver_exit);81 MODULE_LICENSE("GPL");
总体来说,驱动还是传统的字符设备驱动、块设备驱动或网络设备驱动,只是套上了一张“”的皮,目的是为了使用总线、驱动和设备这个驱动模型来实现驱动的分离与分层 。
设备
如果内核支持设备树的话就不要再使用来描述设备了,因为改用设备树去描述了 。当然了,你如果一定要用来描述设备信息的话也是可以的 。
22 struct platform_device {23 const char *name; 24 int id; 25 bool id_auto;26 struct device dev;27 u32 num_resources; 28 struct resource *resource;2930 const struct platform_device_id *id_entry;31 char *driver_override; /* Driver name to force a match */3233 /* MFD cell pointer */34 struct mfd_cell *mfd_cell;3536 /* arch specific additions */37 struct pdev_archdata archdata;38 };