Linux MISC 驱动实验

news/2024/4/19 0:54:22

misc 的意思是混合、杂项的,因此 MISC 驱动也叫做杂项驱动,也就是当我们板子上的某 些外设无法进行分类的时候就可以使用 MISC 驱动。MISC 驱动其实就是最简单的字符设备驱 动,通常嵌套在 platform 总线驱动中,实现复杂的驱动。

MISC 设备驱动简介

所有的 MISC 设备驱动的主设备号都为 10,不同的设备使用不同的从设备号。随着 Linux 字符设备驱动的不断增加,设备号变得越来越紧张,尤其是主设备号,MISC 设备驱动就用于解 决此问题。MISC 设备会自动创建 cdev,不需要像我们以前那样手动创建,因此采用 MISC 设 备驱动可以简化字符设备驱动的编写。我们需要向 Linux 注册一个 miscdevice 设备,miscdevice 是一个结构体,定义在文件 include/linux/miscdevice.h 中

struct miscdevice {int minor; /* 子设备号 */const char *name; /* 设备名字 */ const struct file_operations *fops; /* 设备操作集 */struct list_head list;struct device *parent;struct device *this_device;const struct attribute_group **groups;const char *nodename;umode_t mode;};

定义一个 MISC 设备(miscdevice 类型)以后我们需要设置 minor、name 和 fops 这三个成员 变量。minor 表示子设备号,MISC 设备的主设备号为 10,这个是固定的,需要用户指定子设备 号,Linux 系统已经预定义了一些 MISC 设备的子设备号,这些预定义的子设备号定义在 include/linux/miscdevice.h 文件中

#define PSMOUSE_MINOR 1#define MS_BUSMOUSE_MINOR 2 /* unused */#define ATIXL_BUSMOUSE_MINOR 3 /* unused *//*#define AMIGAMOUSE_MINOR 4 FIXME OBSOLETE */#define ATARIMOUSE_MINOR 5 /* unused */
#define SUN_MOUSE_MINOR 6 /* unused */
......#define MISC_DYNAMIC_MINOR 255

我们在使用的时候可以从这些预定义的子设备号中挑选一个,当然也可以自己定义,只要 这个子设备号没有被其他设备使用接口。 name 就是此 MISC 设备名字,当此设备注册成功以后就会在/dev 目录下生成一个名为 name 的设备文件。fops 就是字符设备的操作集合,MISC 设备驱动最终是需要使用用户提供的 fops 操作集合。

  • 当设置好 miscdevice 以后就需要使用 misc_register 函数向系统中注册一个 MISC 设备,此 函数原型如下:
int misc_register(struct miscdevice * misc)
/*
函数参数和返回值含义如下:
misc:要注册的 MISC 设备。
返回值:负数,失败;0,成功。
*/

  • 以前我们需要自己调用一堆的函数去创建设备,比如在以前的字符设备驱动中我们会使用 如下几个函数完成设备创建过程:
alloc_chrdev_region(); /* 申请设备号 */cdev_init(); /* 初始化 cdev */cdev_add(); /* 添加 cdev */class_create(); /* 创建类 */device_create(); /* 创建设备 */

 

  • 现在我们可以直接使用 misc_register 一个函数来完成。当我 们卸载设备驱动模块的时候需要调用 misc_deregister 函数来注销掉 MISC 设备,函数原型如下:
int misc_deregister(struct miscdevice *misc)
/*
函数参数和返回值含义如下:
misc:要注销的 MISC 设备。
返回值:负数,失败;0,成功。
*/
  • 以前注销设备驱动的时候,我们需要调用一堆的函数去删除此前创建的 cdev、设备等等内 容,如下所示:
  • 现在我们只需要一个 misc_deregister 函数即可完成
cdev_del(); /* 删除 cdev */
unregister_chrdev_region(); /* 注销设备号 */
device_destroy(); /* 删除设备 */
class_destroy(); /* 删除类 */

beep 驱动程序编写

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>#define MISCBEEP_NAME		"miscbeep"	/* 名字 	*/
#define MISCBEEP_MINOR		144			/* 子设备号 */
#define BEEPOFF 			0			/* 关蜂鸣器 */
#define BEEPON 				1			/* 开蜂鸣器 *//* miscbeep设备结构体 */
struct miscbeep_dev{dev_t devid;			/* 设备号 	 */struct cdev cdev;		/* cdev 	*/struct class *class;	/* 类 		*/struct device *device;	/* 设备 	 */struct device_node	*nd; /* 设备节点 */int beep_gpio;			/* beep所使用的GPIO编号		*/
};struct miscbeep_dev miscbeep;		/* beep设备 */static int miscbeep_open(struct inode *inode, struct file *filp)
{filp->private_data = &miscbeep; /* 设置私有数据 */return 0;
}static ssize_t miscbeep_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{int retvalue;unsigned char databuf[1];unsigned char beepstat;struct miscbeep_dev *dev = filp->private_data;retvalue = copy_from_user(databuf, buf, cnt);if(retvalue < 0) {printk("kernel write failed!\r\n");return -EFAULT;}beepstat = databuf[0];		/* 获取状态值 */if(beepstat == BEEPON) {	gpio_set_value(dev->beep_gpio, 0);	/* 打开蜂鸣器 */} else if(beepstat == BEEPOFF) {gpio_set_value(dev->beep_gpio, 1);	/* 关闭蜂鸣器 */}return 0;
}/* 设备操作函数 */
static struct file_operations miscbeep_fops = {.owner = THIS_MODULE,.open = miscbeep_open,.write = miscbeep_write,
};/* MISC设备结构体 */
static struct miscdevice beep_miscdev = {.minor = MISCBEEP_MINOR,.name = MISCBEEP_NAME,.fops = &miscbeep_fops,
};static int miscbeep_probe(struct platform_device *dev)
{int ret = 0;printk("beep driver and device was matched!\r\n");/* 设置BEEP所使用的GPIO *//* 1、获取设备节点:beep */miscbeep.nd = of_find_node_by_path("/beep");if(miscbeep.nd == NULL) {printk("beep node not find!\r\n");return -EINVAL;} /* 2、 获取设备树中的gpio属性,得到BEEP所使用的BEEP编号 */miscbeep.beep_gpio = of_get_named_gpio(miscbeep.nd, "beep-gpio", 0);if(miscbeep.beep_gpio < 0) {printk("can't get beep-gpio");return -EINVAL;}/* 3、设置GPIO5_IO01为输出,并且输出高电平,默认关闭BEEP */ret = gpio_direction_output(miscbeep.beep_gpio, 1);if(ret < 0) {printk("can't set gpio!\r\n");}/* 一般情况下会注册对应的字符设备,但是这里我们使用MISC设备* 所以我们不需要自己注册字符设备驱动,只需要注册misc设备驱动即可*/ret = misc_register(&beep_miscdev);if(ret < 0){printk("misc device register failed!\r\n");return -EFAULT;}return 0;
}static int miscbeep_remove(struct platform_device *dev)
{/* 注销设备的时候关闭LED灯 */gpio_set_value(miscbeep.beep_gpio, 1);/* 注销misc设备 */misc_deregister(&beep_miscdev);return 0;
}/* 匹配列表 */static const struct of_device_id beep_of_match[] = {{ .compatible = "atkalpha-beep" },{ /* Sentinel */ }};/* platform驱动结构体 */
static struct platform_driver beep_driver = {.driver     = {.name   = "imx6ul-beep",         /* 驱动名字,用于和设备匹配 */.of_match_table = beep_of_match, /* 设备树匹配表          */},.probe      = miscbeep_probe,.remove     = miscbeep_remove,
};static int __init miscbeep_init(void)
{return platform_driver_register(&beep_driver);
}static void __exit miscbeep_exit(void)
{platform_driver_unregister(&beep_driver);
}module_init(miscbeep_init);
module_exit(miscbeep_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zuozhongkai");

编写测试 APP

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"#define BEEPOFF	0
#define BEEPON 	1int main(int argc, char *argv[])
{int fd, retvalue;char *filename;unsigned char databuf[1];if(argc != 3){printf("Error Usage!\r\n");return -1;}filename = argv[1];fd = open(filename, O_RDWR);	/* 打开beep驱动 */if(fd < 0){printf("file %s open failed!\r\n", argv[1]);return -1;}databuf[0] = atoi(argv[2]);	/* 要执行的操作:打开或关闭 */retvalue = write(fd, databuf, sizeof(databuf));if(retvalue < 0){printf("BEEP Control Failed!\r\n");close(fd);return -1;}retvalue = close(fd); /* 关闭文件 */if(retvalue < 0){printf("file %s close failed!\r\n", argv[1]);return -1;}return 0;
}

运行测试

进入到目录 lib/modules/4.1.15 中,输入如下命令 加载 miscbeep.ko 这个驱动模块。

depmod   //第一次加载驱动的时候需要运行此命令

modprobe miscbeep.ko   //加载设备模块

当驱动模块加载成功以后我们可以在/sys/class/misc 这个目录下看到一个名为“miscbeep” 的子目录

 所有的 misc 设备都属于同一个类,/sys/class/misc 目录下就是 misc 这个类的所有设备,每 个设备对应一个子目录。 驱动与设备匹配成功以后就会生成/dev/miscbeep 这个设备驱动文件,输入如下命令查看这 个文件的主次设备号:

ls /dev/miscbeep -l

 输入如下命令打开 BEEP:

./miscbeepApp /dev/miscbeep 1         //打开 BEEP

在输入如下命令关闭 LED 灯:

./miscbeepApp /dev/miscbeep 0    //关闭 BEEP

观察一下 BEEP 能否打开和关闭,如果可以的话就说明驱动工作正常,如果要卸载驱动的 话输入如下命令即可: rmmod miscbeep.ko


http://www.ppmy.cn/news/73371.html

相关文章

Less和sass安装及使用

CSS预处理器 由来 CSS本身不是一种编程语言。你可以用它开发网页样式&#xff0c;但是没法用它编程。换句话说&#xff0c;CSS基本上是设计师的工具&#xff0c;不是程序员的工具。它并不像其它程序语言&#xff0c;比如说JavaScript等&#xff0c;有自己的变量、常量、条件语…

C#中使用git将项目代码上传到远程仓库的操作

一、远程仓库创建操作&#xff08;远程仓库使用的是gitHub&#xff09; 1、登录GitHub官网&#xff0c;注册登录账号后&#xff0c;点击创建仓库 2、仓库名称命名&#xff0c;如下所示&#xff1a; 3、创建成功如下所示&#xff1a;获得https协议&#xff08;https://github.c…

JuiceFS 在多云存储架构中的应用 | 深势科技分享

2020 年末&#xff0c;谷歌旗下 DeepMind 研发的 AI 程序 AlphaFold2 在国际蛋白质结构预测竞赛上取得惊人的准确度&#xff0c;使得 “AI 预测蛋白质结构” 这一领域受到了空前的关注。今天我们邀请到同领域企业&#xff0c;深势科技为大家分享其搭建基础平台时的实践与思考。…

在阿里做了6年软件测试,4月无情被辞,想给划水的兄弟提个醒

先简单交代一下背景吧&#xff0c;某不知名 985 的本硕&#xff0c;17 年毕业加入阿里&#xff0c;以“人员优化”的名义无情被裁员&#xff0c;之后跳槽到了有赞&#xff0c;一直从事软件测试的工作。之前没有实习经历&#xff0c;算是6年的工作经验吧。 这6年之间完成了一次…

python 图片保存成视频

&#x1f468;‍&#x1f4bb;个人简介&#xff1a; 深度学习图像领域工作者 &#x1f389;工作总结链接&#xff1a;https://blog.csdn.net/qq_28949847/article/details/128552785 链接中主要是个人工作的总结&#xff0c;每个链接都是一些常用demo&#xff0c…

洛谷 池塘计数 floor-fill BFS 模板题

&#x1f351; OJ专栏 &#x1f351; P1596 Lake Counting 题面翻译 由于近期的降雨&#xff0c;雨水汇集在农民约翰的田地不同的地方。我们用一个 N M ( 1 ≤ N ≤ 100 , 1 ≤ M ≤ 100 ) N\times M(1\leq N\leq 100, 1\leq M\leq 100) NM(1≤N≤100,1≤M≤100) 的网格图表…

Qt——Qt控件之显示窗口-QLabel标签控件的使用总结(例程:QLabel显示文本标签及图片)

【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来! 《项目案例分享》 《极客DIY开源分享》 《嵌入式通用开发实战》 《C++语言开发基础总结》 《从0到1学习嵌入式Linux开发》

【CSS 选择器应用在QSS】第二天

CSS 选择器应用在QSS 【1】元素选择器&#xff08;元素通用性&#xff09;【2】id 选择器&#xff08;唯一性&#xff09;【2.1】CSS【2.2】QSS 【3】类选择器【3.1】CSS【3.2】QSS 【4】类选择器&#xff08;只针对指定元素&#xff09;【4.1】CSS【4.2】QSS 【5】通用选择器【…

语音合成工具_bark

1 介绍 多语言的文字转语音模型。 地址: https://github.com/suno-ai/bark 2 模型原理 Bark通过三个Transformer模型&#xff0c;将文本转换为音频。 2.1 文本到语义Token 输入&#xff1a;由Hugging Face的BERT标记器分词的文本 输出&#xff1a;编码生成音频的语义Token…

【面试高频 time: 2023-5-18】做分布式文件存储,如何保证分布式存储的高性能与高可用?

大家可以想到基本就是副本备份、双活、多活这种架构 在系统中通过复制协议将数据同步到多个存储节点&#xff0c;并确 保多个副本之间的数据⼀致性&#xff0c;当某个存储节点出故障 时&#xff0c;系统能够⾃动将服务切换到其他的副本 在分布式存储中⾼性能与⾼可⽤是⽭盾的&…

手把手教你怎么搭建自己的ChatGPT和Midjourney绘图(含源码)

AI程序采用NUXT3LARAVEL9开发&#xff08;目前版本V1.1.7&#xff09; 授权方式&#xff1a;三个顶级域名两次更换 1.AI智能对话-对接官方和官方反代&#xff08;markdown输出&#xff09;PS:采用百度与自用库检测文字 2.AI绘图-根据关键词绘图-增加dreamStudio绘画-增加mid…

Requests的使用例子

Requests库是一个Python HTTP客户端库&#xff0c;用于向Web服务器发送HTTP请求。它提供了简单而直观的API&#xff0c;使得向Web服务器发送HTTP请求变得非常容易。以下是Requests库的一些功能和示例&#xff1a; 1、发送HTTP GET请求 发送HTTP GET请求非常简单&#xff0c;只…

查看linux日志以及处理不能登录mysql的错误

要查看MariaDB的日志文件&#xff0c;可以使用以下命令&#xff1a; 1. 错误日志文件&#xff1a; bash sudo cat /var/log/mariadb/error.log 这将显示MariaDB的错误日志文件的内容。如果在默认位置找不到错误日志文件&#xff0c;您可以尝试查找其他可能的位置&#…

Activiti实战——Springboot整合Activiti

目录 一、Activiti数据库表名说明 二、Spring boot整合activiti 1. 创建springboot项目 2. 引入activiti依赖及项目依赖 3. 配置数据源 &#xff08;1&#xff09;创建数据源配置文件 &#xff08;2&#xff09;配置文件 4. 配置Acitviti引擎 5. 启动项目 三、Activiti…

DJ5-4 交换局域网(第一节课)

目录 一、局域网概述 1、LAN 的特点和分类 2、常见的网络拓扑结构 二、计算机与局域网的连接 三、局域网体系结构 四、链路层寻址地址 1、MAC 地址分配 2、MAC 地址识别 五、ARP 地址解析协议 1、ARP 地址解析协议 2、ARP&#xff1a;两个主机位于同一个局域网 3、…

Godot引擎 4.0 文档 - 入门介绍 - Godot 关键概念概述¶

本文为Google Translate英译中结果&#xff0c;DrGraph在此基础上加了一些校正。英文原版页面&#xff1a;Overview of Godots key concepts — Godot Engine (stable) documentation in English Godot 关键概念概述 每个游戏引擎都围绕您用来构建应用程序的抽象展开。在 Godo…

AUTOSAR知识点 之 COM (二):ISOLAR-AB的配置

目录 1、概述 2、ISOLAR-AB配置 2.1、ComGeneral 2.2、ComConfig 2.2.1、ComGwMapping 2.2.2、ComIPduGroups 2.2.3、ComIPdus

超越大数据的边界:Apache Flink实战解析【上进小菜猪大数据系列】

上进小菜猪&#xff0c;沈工大软件工程专业&#xff0c;爱好敲代码&#xff0c;持续输出干货。欢迎订阅专栏 Apache Flink是一种快速、可靠、可扩展的开源流处理框架&#xff0c;被广泛应用于大数据领域。本文将介绍Apache Flink的实战运用&#xff0c;包括其核心概念、架构设…

LeetCode346场周赛

2023.5.21LeetCode346场周赛 A. 删除子串后的字符串最小长度 思路 使用栈模拟&#xff0c;每当遇到AB和CD时出栈 代码 class Solution { public:int minLength(string s) {string res s.substr(0, 1);for (int i 1; i < s.size(); i ) {res s[i];int n res.size()…

选择性搜索算法(Selective Search )——SS算法

文章目录 一、前言二、object Detection VS object Recognition&#xff08;Selective Search的提出&#xff09;2.1object recognition与object detection的关系2.2滑动窗口方法的局限性2.3Selective search算法的提出 三、Selective Search算法3.1什么是Selective Search&…