☰
实现 Android 字符设备驱动
2026/10/14 21:07:35 网站建设 项目流程

这个模块共有四篇:
1.实现 Android 字符设备驱动
2.Android 15 及以上版本创建系统级 app 并测试驱动
3.在 Android 系统中自定义 LedManagerService 服务并提供给 app 使用
4.为 LedManagerService 添加区权限申请功能

一、开发环境

  • LineageOS 23.2 (Android 16)
  • Ubuntu 24.04.4 LTS
  • 红米9 (lancelot)已解锁 BL 并刷如 LineageOS 23.2

二、实现字符设备驱动

这里以模拟LED为例,实现一个字符设备驱动,用于控制LED的亮灭。

  1. 首先,在 YourSource/kernel/xiaomi/mt6768/drivers/char 目录下创建一个目录 myled,用于存放字符设备驱动的源文件。

  2. 创建驱动文件 YourSource/kernel/xiaomi/mt6768/drivers/char/myled/myled.c

    #include<linux/module.h>#include<linux/kernel.h>#include<linux/init.h>#include<linux/fs.h>#include<linux/cdev.h>#include<linux/uaccess.h>#include<linux/miscdevice.h>#defineLED_ON1#defineLED_OFF0staticintled_fd=-1;staticintled_state=LED_OFF;staticssize_tmyled_write(structfile*filp,constchar__user*buf,size_tcount,loff_t*f_pos){printk(KERN_ALERT"############# myled_write ########\n");charled_on;if(count!=1)return-EINVAL;if(copy_from_user(&led_on,buf,1))return-EFAULT;if(led_on==LED_ON&&led_state!=LED_ON){// 确保LED硬件处于关闭状态再打开// ... 执行打开LED的操作 ...}elseif(led_on==LED_OFF&&led_state!=LED_OFF){// 确保LED硬件处于打开状态再关闭// ... 执行关闭LED的操作 ...}else{// 如果请求的LED状态与当前状态相同,则无需操作return0;}led_state=led_on?LED_ON:LED_OFF;return1;}staticssize_tmyled_read(structfile*file,char__user*buf,size_tcount,loff_t*ppos){printk(KERN_ALERT"############# myled_read ########\n");// 实现读逻辑return0;}staticconststructfile_operationsmyled_fops={.owner=THIS_MODULE,.read=myled_read,.write=myled_write,};staticstructmiscdevicemyled_misc={.minor=MISC_DYNAMIC_MINOR,.name="myled",.fops=&myled_fops,.mode=0666,// 根据安全需求调整,这里设置无效,需要单独配置 SELinux 和 UAC 权限};staticint__initled_init(void){// 用 misc_register() 而非 register_chrdev(),因为前者会自动处理设备号分配并触发热插拔事件,简化设备节点的创建// led_fd = register_chrdev(0, "myleddev", &myled_fops);// return 0;returnmisc_register(&myled_misc);}staticvoid__exitled_exit(void){// unregister_chrdev(led_fd, "myleddev");misc_deregister(&myled_misc);}module_init(led_init);module_exit(led_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("LED");MODULE_DESCRIPTION("A simple LED driver for Android.");
  3. 创建配置文件 YourSource/kernel/xiaomi/mt6768/drivers/char/myled/Kconfig

    config MY_LED bool"My Led Test"defaulty help This is a led demo to test kernel experiment On Android.
  4. 创建 Makefile 文件 YourSource/kernel/xiaomi/mt6768/drivers/char/myled/Makefile

    #obj-m 会编译成 myled.o 文件,这里使用 obj-y 直接编译到 boot.img 中obj-y+=myled.o

三、将驱动配置到 kernelconfig 中,配置好后才能编译到 boot.img 中

  1. 在 YourSource/kernel/xiaomi/mt6768/drivers/char/Kconfig 中添加以下内容:
    source"drivers/char/myled/Kconfig"
  2. 在 YourSource/kernel/xiaomi/mt6768/drivers/char/Makefile 中添加以下内容:
    obj-y+=myled/

四、配置 SELinux 权限

  1. 在 YourSource/device/xiaomi/mt6768-common/sepolicy/vendor/file.te 中添加以下内容:
    #myled,为led驱动定义一个设备类型,以方便SELinux权限管理type myled_device,dev_type;
  2. 在 YourSource/device/xiaomi/mt6768-common/sepolicy/vendor/file_contexts 中添加以下内容:
    #myled/dev/myled u:object_r:myled_device:s0
    因为 myled 挂载在 /dev 下面,所以在 file_contexts 中添加上面的权限即可,如果是在 /sys 下面,需要使用 genfscon sysfs 来添加权限(请自行搜索 genfscon sysfs、genfscon debugfs 和 genfscon devtmpfs 的使用方法)。
  3. 在 YourSource/device/xiaomi/mt6768-common/sepolicy/vendor/system_app.te 中添加以下内容:
    #myledallow system_app myled_device:chr_file{getattr open read write ioctl};

五、配置 UAC 权限

  1. 在 YourSource/device/xiaomi/mt6768-common/rootdir/etc/ueventd.mtk.rc 中添加以下内容:
    /dev/myled 0660 system system

六、编译并刷入镜像

  1. 驱动在 boot 分区,需要编译 boot.img 文件
# 编译 boot.img 文件mka bootimage# 进入 fastboot 模式adbrebootbootloader# 刷入 boot.img 文件fastboot flash boot boot.img
  1. SELinux 配置在 vendor 分区,需要编译 vendor.img 文件
# 编译 vendor.img 文件mka vendorimage# android 10 以上需要进入 fastbootd 模式adbrebootfastboot# 刷入 vendor.img 文件fastboot flash vendor vendor.img

七、测试驱动

验证驱动是否刷入成功,执行下面的命令后,显示如下则说明正确配置并刷入了。

(base)test@test:~$ adb shellls-l/dev/myled crw-rw----1system system10,612026-09-2810:55 /dev/myled(base)test@test:~$ adb shellls-Z/dev/myled u:object_r:myled_device:s0 /dev/myled

因为 LED 驱动在 system 域,所以需要创建个系统级 app 来测试驱动。由于 Android 15 及以上版本,在 app 中添加 sharedUserId=“android.uid.system” 并不能实现系统级权限,所以还是在下一篇中介绍怎么处理吧。

八、总结

  1. 驱动在 boot 分区,需要编译 boot.img 文件
  2. SELinux 配置在 vendor 分区,需要编译 vendor.img 文件,而 Android 10 以上需要进入 fastbootd 模式

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询