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

简介: 如何使用Amlogic T972安卓9.0系统上的misc框架来简化驱动程序开发,通过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/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:/ #

命令及效果图示:
在这里插入图片描述

七、源码下载

百看不如一试……

git clone git@gitee.com:amizhou/amlogic_t972_android9_driver.git

八、篇尾

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

相关文章
|
15天前
|
物联网 区块链 vr&ar
未来已来:探索区块链、物联网与虚拟现实技术的融合与应用安卓与iOS开发中的跨平台框架选择
【8月更文挑战第30天】在科技的巨轮下,新技术不断涌现,引领着社会进步。本文将聚焦于当前最前沿的技术——区块链、物联网和虚拟现实,探讨它们各自的发展趋势及其在未来可能的应用场景。我们将从这些技术的基本定义出发,逐步深入到它们的相互作用和集成应用,最后展望它们如何共同塑造一个全新的数字生态系统。
|
3天前
|
编译器 Android开发 开发者
带你了解Android Jetpack库中的依赖注入框架:Hilt
本文介绍了Hilt,这是Google为Android开发的依赖注入框架,基于Dagger构建,旨在简化依赖注入过程。Hilt通过自动化的组件和注解减少了DI的样板代码,提高了应用的可测试性和可维护性。文章详细讲解了Hilt的主要概念、基本用法及原理,帮助开发者更好地理解和应用Hilt。
19 8
|
16天前
|
设计模式 Java Android开发
探索安卓应用开发:从新手到专家的旅程探索iOS开发中的SwiftUI框架
【8月更文挑战第29天】本文旨在通过一个易于理解的旅程比喻,带领读者深入探讨安卓应用开发的各个方面。我们将从基础概念入手,逐步过渡到高级技术,最后讨论如何维护和推广你的应用。无论你是编程新手还是有经验的开发者,这篇文章都将为你提供有价值的见解和实用的代码示例。让我们一起开始这段激动人心的旅程吧!
|
17天前
|
Android开发
基于Amlogic 安卓9.0, 驱动简说(五):基于GPIO、LED子系统的LED驱动
这篇文章是关于如何在基于Amlogic T972的Android 9.0系统上,使用GPIO和LED子系统来实现LED驱动的教程,包括了DTS设备树配置、驱动源码编写以及如何在用户空间控制LED的亮度和开关。
21 0
基于Amlogic 安卓9.0, 驱动简说(五):基于GPIO、LED子系统的LED驱动
|
17天前
|
Android开发
基于Amlogic 安卓9.0, 驱动简说(四):Platform平台驱动,驱动与设备的分离
本文介绍了如何在基于Amlogic T972的Android 9.0系统上使用Platform平台驱动框架和设备树(DTS),实现设备与驱动的分离,并通过静态枚举在设备树中描述设备,自动触发驱动程序的加载和设备创建。
7 0
基于Amlogic 安卓9.0, 驱动简说(四):Platform平台驱动,驱动与设备的分离
|
17天前
|
Android开发 C语言
基于Amlogic 安卓9.0, 驱动简说(二):字符设备驱动,自动创建设备
这篇文章是关于如何在基于Amlogic T972的Android 9.0系统上,通过自动分配设备号和自动创建设备节点文件的方式,开发字符设备驱动程序的教程。
21 0
基于Amlogic 安卓9.0, 驱动简说(二):字符设备驱动,自动创建设备
|
17天前
|
自然语言处理 Shell Linux
基于Amlogic 安卓9.0, 驱动简说(一):字符设备驱动,手动创建设备
本文是关于在Amlogic安卓9.0平台上创建字符设备驱动的教程,详细介绍了驱动程序的编写、编译、部署和测试过程,并提供了完整的源码和应用层调用示例。
32 0
基于Amlogic 安卓9.0, 驱动简说(一):字符设备驱动,手动创建设备
|
17天前
|
传感器 Android开发 芯片
不写一行代码(三):实现安卓基于i2c bus的Slaver设备驱动
本文是系列文章的第三篇,展示了如何在Android系统中利用现有的i2c bus驱动,通过编写设备树节点和应用层的控制代码,实现对基于i2c bus的Slaver设备(如六轴陀螺仪模块QMI8658C)的控制,而无需编写设备驱动代码。
26 0
不写一行代码(三):实现安卓基于i2c bus的Slaver设备驱动
|
17天前
|
Android开发
不写一行代码(二):实现安卓基于PWM的LED设备驱动
本文介绍了在Android系统中不编写任何代码,通过设备树配置和内核支持的通用PWM LED驱动来实现基于PWM的LED设备驱动,并通过测试命令调整LED亮度级别。
25 0
不写一行代码(二):实现安卓基于PWM的LED设备驱动
|
17天前
|
Linux Android开发 C语言
不写一行代码(一):实现安卓基于GPIO的LED设备驱动
本文通过实践操作,展示了在Android系统中不编写任何代码,利用设备树(DTS)配置和内核支持的通用GPIO LED驱动来控制LED设备,并进一步通过C语言编写NDK测试APP来实现LED的闪烁效果。
31 0
不写一行代码(一):实现安卓基于GPIO的LED设备驱动