一、篇头
本文介绍Platform平台驱动框架,使用此框架,将可以用上DTS设备树文件,实现设备的静态枚举,实现设备与驱动的分离。
本文基于Amlogic T972 , Android 9.0, 内核版本 4.9.113
二、系列文章
第1篇:基于Amlogic 安卓9.0, 驱动简说(一):字符设备驱动,手动创建设备
第2篇:基于Amlogic 安卓9.0, 驱动简说(二):字符设备驱动,自动创建设备
第3篇:基于Amlogic 安卓9.0, 驱动简说(三):使用misc框架,让驱动更简单
第4篇:基于Amlogic 安卓9.0, 驱动简说(四):Platform平台驱动,驱动与设备的分离
三、源码解析
3.1 编辑DTS设备树文件
- 如下添加 aml_plat_dev 节点,其compatible 与驱动中of_device_id的设定完全相同
aml_plat_dev {
compatible = "szhou,aml_plat_dev";
};
3.2 解析:驱动源码
- 文件名:helloworld_platform_amlogic_driver.c
- 位置:android9.0\common\drivers\amlogic\input\helloworld_platform_amlogic_driver.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h> /*platform 驱动框架头文件*/
/* 实现系统调用接口:open(),在platform中保持不变 */
static int aml_misc_open(struct inode *inode, struct file *file)
{
pr_info("aml_misc_open()-> platform is called.\n");
return 0;
}
/* 实现系统调用接口:close(),在platform中保持不变 */
static int aml_misc_close(struct inode *inode, struct file *file)
{
pr_info("aml_misc_close()-> platform is called.\n");
return 0;
}
/* 实现系统调用接口:ioctl(),在platform中保持不变 */
static long aml_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
pr_info("aml_misc_ioctl()-> platform is called. cmd = %d, arg = %ld\n", cmd, arg);
return 0;
}
static const struct file_operations aml_misc_fops = {
.owner = THIS_MODULE, /* 固定搭配 */
.open = aml_misc_open, /* 提供open(), fopen()系统调用 */
.release = aml_misc_close, /* 提供close(), fclose()系统调用 */
.unlocked_ioctl = aml_misc_ioctl, /* 提供ioctl()系统调用 */
};
/* 声明 struct miscdevice 结构体变量,并赋值*/
static struct miscdevice aml_misc_device = {
.minor = MISC_DYNAMIC_MINOR, /* 优点:misc设备已由misc框架提供了主设备号,其余设备通过此设定,自动分配一个次设备号*/
.name = "aml_plat_misc_dev", /* 将创建/dev/aml_plat_misc_dev 以及 /sys/class/misc/aml_plat_misc_dev */
.fops = &aml_misc_fops,
};
//static int __init aml_misc_init(void)
//驱动在DTS中探测到相兼容的设备,将自动运行probe初始化,并创建设备,相比misc驱动,只是更换函数接口,实现大体还是一样
static int __init my_probe(struct platform_device *pdev)
{
int ret;
pr_info("aml_misc_init-> my_probe\n");
/* 将miscdevice对象注册进内核 */
ret = misc_register(&aml_misc_device);
if (ret != 0) {
pr_err("Failded: misc_register aml_misc_dev-> my_probe\n");
return ret;
}
pr_info("init alloc aml_misc_dev's minor[%i]-> my_probe\n",aml_misc_device.minor);
return 0;
}
//static void __exit aml_misc_exit(void)
//同样的,用platform的remove替代之前的exit,相比misc驱动,只是更换函数接口,实现大体还是一样
static int __exit my_remove(struct platform_device *pdev)
{
pr_info("aml_misc_exit -> my_remove\n");
/* 注销miscdevice对象 */
misc_deregister(&aml_misc_device);
return 0;
}
/*
* (1) 新增of_device_id,用于与DTS中静态描述的设备做匹配
* (2) 需要在DTS中添加具备 .compatible 属性的节点,否则无法触发 probe()函数的执行
*/
static const struct of_device_id my_of_ids[] = {
{ .compatible = "szhou,aml_plat_dev"},
{},
};
//导出my_of_ids符号,供内核使用
MODULE_DEVICE_TABLE(of, my_of_ids);
/* 定义platform_driver对象,用于注册到内核Platform总线中 */
static struct platform_driver my_platform_driver = {
.probe = my_probe,
.remove = my_remove,
.driver = {
.name = "aml_plat_dev",
.of_match_table = my_of_ids,
.owner = THIS_MODULE,
}
};
/* 注册我们的platform驱动 */
module_platform_driver(my_platform_driver);
/*下面两句可以省略了,驱动在DTS中探测到相兼容的设备,将自动运行probe初始化,并创建设备*/
//module_init(aml_misc_init);
//module_exit(aml_misc_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("szhou <66176468@qq.com>");
MODULE_DESCRIPTION("simple say[3]: misc device driver");
3.3 Makefile
obj-m += helloworld_platform_amlogic_driver.o
四、编译、部署、测试
4.1 编译
参考之前文章,因为需要同时编译KO和DTS文件,直接执行内核编译命令即可。
4.2 烧录
步骤一:复制dt.img到烧录工具夹
步骤二:执行burning.bat程序,烧录dt.img
4.3 KO部署
PS Z:\> adb root
PS Z:\> adb push .\helloworld_platform_amlogic_driver.ko /data/
PS Z:\>
命令图示如下:
4.4 KO加载测试
(1)加载KO之前,可见已有aml_plat_dev设备信息,但却没有 /dev/aml_plat_misc_dev
:/ # cd /sys
:/sys # find . -name aml_plat_dev
./devices/platform/aml_plat_dev
./firmware/devicetree/base/aml_plat_dev
./bus/platform/devices/aml_plat_dev
(2)查看/dev下是否有创建设备文件(尚未创建,需要待驱动insmod后执行probe匹配后才会创建)
:/sys # cd /dev
1|:/dev # ls -l /dev/aml_plat_misc_dev
ls: /dev/aml_plat_misc_dev: No such file or directory
:/dev #
(3)加载KO文件
:/data # insmod helloworld_platform_amlogic_driver.ko
[ 198.651146@3]- type=1400 audit(1672309615.242:1119): avc: denied { getattr } for pid=5274 comm="sh" path="/data/helloworld_platform_amlogic_driver.ko" dev="mmcblk0p20" ino=16 scontext=u:r:install_recovery:s0 tcontext=u:object_r:system_data_file:s0 tclass=file permissive=1
[ 198.652941@2]- aml_misc_init-> my_probe
[ 198.656100@1]- init alloc aml_misc_dev's minor[47]-> my_probe
(4)查看设备添加情况,发现设备已创建:
:/data # ls -l /dev/aml_plat_misc_dev
crw------- 1 root root 10, 47 2022-12-29 18:26 /dev/aml_plat_misc_dev
:/data #
4.5 APP测试
- 直接使用第3篇中所编写的APP即可
130|:/data # ./hello_aml /dev/aml_plat_misc_dev
[ 214.842417@0]- aml_misc_open()-> platform is called.
[ 214.842497@0]- aml_misc_ioctl()-> platform is called. cmd = 18, arg = -1146983912
[ 214.980620@0]- aml_misc_close()-> platform is called.
:/data #
五、源码下载
- 地址:https://gitee.com/amizhou/amlogic_t972_android9_driver/tree/master/index_01_simpleSay_drivers/lesson_04
git clone git@gitee.com:amizhou/amlogic_t972_android9_driver.git
六、篇尾
保持持续学习, 欢迎私信交流。