首先要知道platform是总线中的一种,要实现platform总线先要从总线开始下手。第一阶段:先创建一个mybus总线和为测试match匹配而写的device和driver1、先创建一个
首先要知道platform是总线中的一种,要实现platform总线先要从总线开始下手。
第一阶段:先创建一个mybus总线和为测试match匹配而写的device和driver
1、先创建一个mybus的bus
structbus_type mybustype = { .name = "mybus",/*创建的总线目录为/sys/bus/mybus */ }; EXPORT_SYMBOL(mybustype);///proc/kallsyms staticint__init bustest_init(void){ intret; printk("*****%s****\n", __FUNCTION__); ret = bus_register(&mybustype); if(ret < 0){ printk("bus_register fail\n"); returnret; } return0; }2、一般总线都需要一些属性的描述,也提供获取版本信息的外部接口
3、创建bus属性对象的文件
staticint__init bustest_init(void){ intret; printk("*****%s****\n", __FUNCTION__); ret = bus_register(&mybustype); if(ret < 0){ printk("bus_register fail\n"); returnret; } ret = bus_create_file(&mybustype, &bus_attr_busversion);//创建属性文件 if(ret < 0) { returnret; } return0; }4、给总线完善匹配match函数
staticintmybus_match(structdevice * dev, structdevice_driver * drv){ printk("*****%s****\n", __FUNCTION__); return1;//先默认返回匹配成功 }测试
在mybus总线上创建driver和device
device.c
extern struct bus_type mybustype; void mydevicetest_release(structdevice *dev){ printk("*******%s*******\n", __FUNCTION__); } struct device mydevicetest_device = { .bus_id = "mybusname",//在2.6.3版本中被init_name代替 /*static int my_match(struct device *dev, struct device_driver *driver) { return !strncmp(dev->bus_id, driver->name, strlen(driver->name)); } */ .bus = &mybustype, .release = mydevicetest_release, }; static int __init mydevicetest_init(void){ intret; printk("*******%s*******\n", __FUNCTION__); if(IS_ERR(&mydevicetest_device)){ returnPTR_ERR(&mydevicetest_device); } ret = device_register(&mydevicetest_device); if(ret < 0){ printk("mydevicetest_init fail\n"); return ret; } return0; } driver.c
完整代码下载地址,对应压缩包mybusone
测试结果,看出总线没问题,match强行返回1,可以probe
$ insmod kodir/bustest.ko *****bustest_init**** $ insmod kodir/devicetest.ko *******mydevicetest_init******* $ insmod kodir/drivertest.ko *****mybus_match**** *****mydevice_driver_probe***** $Tip:你可以通过cat /sys/bus/mybus/busversion 查看版本号,也可以echo "..." > /sys/bus/mybus/busversion修改版本号,对应函数会调mybusattrshow和mybusattrstore
第二阶段,从上面的driver和device的注册可以看出,driver和device都要预先知道总线的对象的名称extern structbus_type mybustype;
我们可以在bus中封装对应的driver和device的函数
修改bus.c
修改device.c
//添加mybus.c中封装的device注册注销相关函数mybus_device_register,,mybus_device_unregister extern int mybus_device_register(struct device * dev); extern void mybus_device_unregister(struct device * dev); static int __init mydevicetest_init(void){ //.............. ret = mybus_device_register(&mydevicetest_device); //............ } static void __exit mydevicetest_exit(void){ //............. mybus_device_unregister(&mydevicetest_device); }