misc 的意思是混合、杂项的,因此 MISC 驱动也叫做杂项驱动,也就是当我们板子上的某些外设无法进行分类的时候就可以使用 MISC 驱动。MISC 驱动其实就是最简单的字符设备驱动,通常嵌套在 platform 总线驱动中,实现复杂的驱动,本章我们就来学习一下 MISC 驱动的编写。
MISC 设备驱动简介
所有的 MISC 设备驱动的主设备号都为 10,不同的设备使用不同的从设备号。随着 Linux字符设备驱动的不断增加,设备号变得越来越紧张,尤其是主设备号,MISC 设备驱动就用于解决此问题。MISC 设备会自动创建 cdev,不需要像我们以前那样手动创建,因此采用 MISC 设备驱动可以简化字符设备驱动的编写。我们需要向 Linux 注册一个 miscdevice 设备,miscdevice是一个结构体,定义在文件 include/linux/miscdevice.h 中,内容如下:
定义一个 MISC 设备(miscdevice 类型)以后我们需要设置 minor、name 和 fops 这三个成员变量。minor 表示子设备号,MISC 设备的主设备号为 10,这个是固定的,需要用户指定子设备号,Linux 系统已经预定义了一些 MISC 设备的子设备号,这些预定义的子设备号定义在include/linux/miscdevice.h 文件中,如下所示:
我们在使用的时候可以从这些预定义的子设备号中挑选一个,当然也可以自己定义,只要这个子设备号没有被其他设备使用。
name 就是此 MISC 设备名字,当此设备注册成功以后就会在/dev 目录下生成一个名为 name的设备文件(自动创建设备节点)。fops 就是字符设备的操作集合,MISC 设备驱动最终是需要使用用户提供的 fops操作集合。
当设置好 miscdevice 以后就需要使用 misc_register 函数向系统中注册一个 MISC 设备,此函数原型如下:
int misc_register(struct miscdevice * misc)
函数参数和返回值含义如下:
misc:要注册的 MISC 设备。
返回值:负数,失败;0,成功。
以前我们需要自己调用一堆的函数去创建设备,比如在以前的字符设备驱动中我们会使用如下几个函数完成设备创建过程:
现在我们可以直接使用 misc_register 一个函数来完成示例代码 57.1.3 中的这些步骤。当我们卸载设备驱动模块的时候需要调用 misc_deregister 函数来注销掉 MISC 设备,函数原型如下:
int misc_deregister(struct miscdevice *misc)
函数参数和返回值含义如下:
misc:要注销的 MISC 设备。
返回值:负数,失败;0,成功。
以前注销设备驱动的时候,我们需要调用一堆的函数去删除此前创建的 cdev、设备等等内容,如下所示:
现在我们只需要一个 misc_deregister 函数即可完成示例代码 57.1.4 中的这些工作。关于MISC 设备驱动就讲解到这里,接下来我们就使用 platform 加 MISC 驱动框架来编写 beep 蜂鸣器驱动。
实验程序编写
本实验对应的例程路径为:开发板光盘-> 2、Linux 驱动例程-> 17_misc。
本章实验我们采用 platform 加 misc 的方式编写 beep 驱动,这也是实际的 Linux 驱动中很常用的方法。采用 platform 来实现总线、设备和驱动,misc 主要负责完成字符设备的创建。
修改设备树
本章实验我们需要用到蜂鸣器,因此需要在 imx6ull-alientek-emmc.dts 文件中创建蜂鸣器设备节点,这里我们直接使用 46.3.1 小节创建的 beep 这个设备节点即可。
beep 驱动程序编写
新建名为“19_miscbeep”的文件夹,然后在 19_miscbeep 文件夹里面创建 vscode 工程,工作区命名为“miscbeep。新建名为 miscbeep.c 的驱动文件,在 miscbeep.c 中输入如下所示内容:
第 29~94 行,标准的字符设备驱动。
第 97~101 行,MISC 设备 beep_miscdev,第 98 行设置子设备号为 144,第 99 行设置设备名字为“miscbeep”,这样当系统启动以后就会在/dev/目录下存在一个名为“miscbeep”的设备文件(我们最终需要的也就是这个设备节点)。第 100 行,设置 MISC 设备的操作函数集合,为 file_operations 类型。
第 109~145 行,platform 框架的 probe 函数,当驱动与设备匹配以后此函数就会执行,首先在此函数中初始化 BEEP 所使用的 IO。最后在 138 行通过 misc_register 函数向 Linux 内核注册MISC 设备,也就是前面定义的 beep_miscdev。
第 152~160 行,platform 框架的 remove 函数,在此函数中调用 misc_deregister 函数来注销MISC 设备。
第 163~196,标准的 platform 驱动。
运行测试
将 上 一 小 节 编 译 出 来 miscbeep.ko 和 miscbeepApp 这 两 个 文 件 拷 贝 到rootfs/lib/modules/4.1.15 目录中,重启开发板,进入到目录 lib/modules/4.1.15 中,输入如下命令加载 miscbeep.ko 这个驱动模块。
当驱动模块加载成功以后我们可以在/sys/class/misc 这个目录下看到一个名为“miscbeep”的子目录,如图 57.4.2.1 所示:
所有的 misc 设备都属于同一个类,/sys/class/misc 目录下就是 misc 这个类的所有设备,每个设备对应一个子目录。
驱动与设备匹配成功以后就会生成/dev/miscbeep 这个设备驱动文件,输入如下命令查看这个文件的主次设备号:
ls /dev/miscbeep -l
结果如图 57.4.2.2 所示:
从图 57.4.2.2 可以看出,/dev/miscbeep 这个设备的主设备号为 10,次设备号为 144,和我们驱动程序里面设置的一致。
输入如下命令打开 BEEP:
./miscbeepApp /dev/miscbeep 1 //打开 BEEP
在输入如下命令关闭 LED 灯:
./miscbeepApp /dev/miscbeep 0 //关闭 BEEP
观察一下 BEEP 能否打开和关闭,如果可以的话就说明驱动工作正常,如果要卸载驱动的话输入如下命令即可:
rmmod miscbeep.ko