基于Amlogic 安卓9.0, 驱动简说(三):使用misc框架,让驱动更简单

一、前文总结

  • 在第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框架,让驱动更简单
第4篇:基于Amlogic 安卓9.0, 驱动简说(四):Platform平台驱动,驱动与设备的分离


三、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/PSWindows1)部署
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

八、篇尾

保持持续学习, 欢迎私信交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿迷创客

感谢!您的支持是我写作的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值