文章目录
- 一、前文总结
- 二、系列文章
- 三、MISC框架驱动
- 四、解析:完整源码
- 4.1 helloworld_misc_amlogic_driver.c
- 4.2 Makefile
- 五、编译执行
- (1)编译及部署
- (2)运行
- 六、应用层调用
- 6.1 APP源码
- 6.2 命令及运行效果
- 七、源码下载
- 八、篇尾
一、前文总结
- 在第1篇文章《驱动简说(一):字符设备驱动,手动创建设备》中,我们了解了基础的字符设备驱动的写法,但也注意到了它的缺点:
- 设备号需要自己去找,自己创建(容易冲突) ;
- 需要自己创建和驱动匹配的设备文件(否则应用层无设备可用)。
- 在第2篇文章《驱动简说(二):字符设备驱动,自动创建设备》中,我们通过alloc自动分配设备号,以及主动注册class、device对象,解决了第1篇的两个问题。
- 但是…… 我们还有更简单的方法,达到第2篇的目的,但不需要写第2篇的那么多代码!
本文基于Amlogic T972 , Android 9.0, 内核版本 4.9.113
二、系列文章
第1篇:基于Amlogic 安卓9.0, 驱动简说(一):字符设备驱动,手动创建设备
第2篇:基于Amlogic 安卓9.0, 驱动简说(二):字符设备驱动,自动创建设备
第3篇:基于Amlogic 安卓9.0, 驱动简说(三):使用misc框架,让驱动更简单
三、MISC框架驱动
misc 驱动框架,直译过来就是杂项设备驱动框架。使用此框架,misc框架将自动为你分配主次设备号,同时会为你在/dev目录下,以及/sys/class/misc目录下创建你的设备文件。
更重要的是,基于系统自动分配(其实只分配了一个次设备号,主设备号与所有misc共用),减少了设备号冲突,更减少了主设备号的资源浪费。同时也减少了类似class/device创建、注销的模块化代码!
四、解析:完整源码
4.1 helloworld_misc_amlogic_driver.c
- 文件,参考位置:android9.0\common\drivers\amlogic\input\helloworld_misc_amlogic_driver.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h> /*misc 驱动框架头文件*/
/* 实现系统调用接口:open() */
static int aml_misc_open(struct inode *inode, struct file *file)
{
pr_info("aml_misc_open() is called.\n");
return 0;
}
/* 实现系统调用接口:close() */
static int aml_misc_close(struct inode *inode, struct file *file)
{
pr_info("aml_misc_close() is called.\n");
return 0;
}
/* 实现系统调用接口:ioctl() */
static long aml_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
pr_info("aml_misc_ioctl() 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_misc_dev", /* 将创建/dev/aml_misc_dev 以及 /sys/class/misc/aml_misc_dev */
.fops = &aml_misc_fops,
};
/*
* 模块初始化接口
* 对比之前两篇文章的例子,可见此版本,有如下几个优点
* (1)不需去申请设备号
* (2)不需去创建和注册 struct class
* (3)不需去创建和注册 struct device
* (4)省去了一大堆,申请、注册的异常判断语句
*/
static int __init aml_misc_init(void)
{
int ret;
pr_info("aml_misc_init\n");
/* 将miscdevice对象注册进内核 */
ret = misc_register(&aml_misc_device);
if (ret != 0) {
pr_err("Failded: misc_register aml_misc_dev\n");
return ret;
}
pr_info("init alloc aml_misc_dev's minor[%i]\n",aml_misc_device.minor);
return 0;
}
/*同初始化函数,退出时候,也不需执行Major/Minor的反注册 */
static void __exit aml_misc_exit(void)
{
pr_info("aml_misc_exit\n");
/* 注销miscdevice对象 */
misc_deregister(&aml_misc_device);
}
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");
4.2 Makefile
- android9.0\common\drivers\amlogic\input\Makefile
- 添加下面语句,并将helloworld_misc_amlogic_driver.c放在同一目录下
obj-m += helloworld_misc_amlogic_driver.o
五、编译执行
(1)编译及部署
参考系列文章,第1篇
(2)运行
- 串口上执行
(1)加载驱动模块
:/data # insmod helloworld_misc_amlogic_driver.ko
[ 3950.099788@3]- aml_misc_init
[ 3950.100480@0]- init alloc aml_misc_dev's minor[47]
:/data #
(2)查看设备文件
:/data # ls -l /dev/aml_misc_dev
crw------- 1 root root 10, 47 2022-12-29 11:12 /dev/aml_misc_dev
:/data # ls -l /sys/class/misc/aml_mis*
lrwxrwxrwx 1 root root 0 2022-12-29 11:13 /sys/class/misc/aml_misc_dev -> ../../devices/virtual/misc/aml_misc_dev
:/data #
效果如下图:
六、应用层调用
因为设备节点文件的名称变成了/dev/aml_misc_dev, 所以不能直接使用第1篇的APP程序进行测试,稍微修改一下
- 如下如有疑问,可参考第1篇,或留言
6.1 APP源码
- 文件:android9.0\development\hello_aml\hello_aml.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
/*
* 使用argv[1]来传入,需要打开的设备文件的路径
* 用法: #./data/hello_aml /dev/aml_misc_dev
*/
int main(int argc, char *argv[])
{
int buf[4]={0};
int fd=0;
if(argc < 2){
printf("Usage: hello_aml /dev/aml_misc_dev\n");
return 0;
}
//(1) 测试 open
fd = open(argv[1], O_RDWR);
if(fd == -1){
printf("Failed: open %s \n", argv[1]);
return 0;
}
//(2) 测试 ioctl
ioctl(fd, 0x12, buf);
//(3) 测试 clsoe
close(fd);
return 0;
}
6.2 命令及运行效果
Windows PowerShell
版权所有(C) Microsoft Corporation。保留所有权利。
安装最新的 PowerShell,了解新功能和改进!https://aka.ms/PSWindows
(1)部署
PS Z:\T972\android_x301\source\t962x3-t972-android9.0\out\target\product\x301\system\bin> adb root
adbd is already running as root
PS Z:\T972\android_x301\source\t962x3-t972-android9.0\out\target\product\x301\system\bin> adb push .\hello_aml /data/
.\hello_aml: 1 file pushed, 0 skipped. 0.8 MB/s (15988 bytes in 0.020s)
(2)修改权限
PS Z:\T972\android_x301\source\t962x3-t972-android9.0\out\target\product\x301\system\bin> adb shell chmod 777 /data/hello_aml
(3)查看设备文件
PS Z:\T972\android_x301\source\t962x3-t972-android9.0\out\target\product\x301\system\bin> adb shell
x301:/ # ls -l /dev/aml_mi*
crw------- 1 root root 10, 47 2022-12-29 11:31 /dev/aml_misc_dev
(4)执行APP
x301:/ # ./data/hello_aml /dev/aml_misc_dev
(5)查看打印
x301:/ # dmesg | tail
[ 5143.465058] aml_misc_open() is called.
[ 5143.465112] aml_misc_ioctl() is called. cmd = 18, arg = -1146418760
[ 5143.470051] aml_misc_close() is called.
x301:/ #
命令及效果图示:
七、源码下载
百看不如一试……
- 地址:https://gitee.com/amizhou/amlogic_t972_android9_driver/tree/master/index_01_simpleSay_drivers/lesson_03
git clone git@gitee.com:amizhou/amlogic_t972_android9_driver.git
八、篇尾
保持持续学习, 欢迎私信交流。