首页 > 系统相关 >Linux MISC 驱动实验学习

Linux MISC 驱动实验学习

时间:2024-07-03 10:19:29浏览次数:15  
标签:struct misc MISC beep Linux 驱动 设备

Linux MISC 驱动实验学习

misc 的意思是混合、杂项的,因此 MISC 驱动也叫做杂项驱动,也就是当我们板子上的某些外设无法进行分类的时候就可以使用 MISC 驱动。

MISC 设备驱动简介

MISC 设备驱动就用于解决此问题。 MISC 设备会自动创建 cdev,不需要像我们以前那样手动创建,因此采用 MISC 设备驱动可以简化字符设备驱动的编写。我们需要向 Linux 注册一个 miscdevice 设备, miscdevice是一个结构体,定义在文件 include/linux/miscdevice.h 中,内容如下:

示例代码 57.1.1 miscdevice 结构体代码
57 struct miscdevice {
58 int minor; /* 子设备号 */
59 const char *name; /* 设备名字 */
60 const struct file_operations *fops; /* 设备操作集 */
61 struct list_head list;
62 struct device *parent;
63 struct device *this_device;
64 const struct attribute_group **groups;
65 const char *nodename;
66 umode_t mode;
67 };

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

示例代码 57.1.2 预定义的 MISC 设备子设备号
13 #define PSMOUSE_MINOR 1
14 #define MS_BUSMOUSE_MINOR 2 /* unused */
15 #define ATIXL_BUSMOUSE_MINOR 3 /* unused */
16 /*#define AMIGAMOUSE_MINOR 4 FIXME OBSOLETE */
17 #define ATARIMOUSE_MINOR 5 /* unused */
18 #define SUN_MOUSE_MINOR 6 /* unused */
......
52 #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,成功。

以前我们需要自己调用一堆的函数去创建设备,比如在以前的字符设备驱动中我们会使用如下几个函数完成设备创建过程:

示例代码 57.1.3 传统的创建设备过程
1 alloc_chrdev_region(); /* 申请设备号 */
2 cdev_init(); /* 初始化 cdev */
3 cdev_add(); /* 添加 cdev */
4 class_create(); /* 创建类 */
5 device_create(); /* 创建设备 */

可以直接使用 misc_register 一个函数来完成示例代码 57.1.3 中的这些步骤。当我们卸载设备驱动模块的时候需要调用 misc_deregister 函数来注销掉 MISC 设备,函数原型如下:

int misc_deregister(struct miscdevice *misc)
函数参数和返回值含义如下:
misc:要注销的 MISC 设备。
返回值: 负数,失败; 0,成功。

注销设备驱动的时候,我们需要调用一堆的函数去删除此前创建的 cdev、设备等等内容,如下所示:

示例代码 57.1.4 传统的删除设备的过程
1 cdev_del(); /* 删除 cdev */
2 unregister_chrdev_region(); /* 注销设备号 */
3 device_destroy(); /* 删除设备 */
4 class_destroy(); /* 删除类 */

现在我们只需要一个 misc_deregister 函数即可完成示例代码 57.1.4 中的这些工作。关于MISC 设备驱动就讲解到这里,接下来我们就使用 platform 加 MISC 驱动框架来编写 beep 蜂鸣器驱动:

程序编写

修改设备树

本章实验我们需要用到蜂鸣器,因此需要在 imx6ull-alientek-emmc.dts 文件中创建蜂鸣器设备节点,这里我们直接使用之前创建的 beep 这个设备节点即可。

beep 驱动程序编写

驱动程序与之前编写的不同之处就是主要是注册设备这块。

/* 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;
}

/*
 * @description     : platform驱动的remove函数,移除platform驱动的时候此函数会执行
 * @param - dev     : platform设备
 * @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;
}

标签:struct,misc,MISC,beep,Linux,驱动,设备
From: https://www.cnblogs.com/bathwind/p/18281104

相关文章

  • 面试题:Linux 系统基础提问 (一)
    Linux系统中如何管理用户和组?Linux系统中用户和组的管理通常包括以下几个方面:1、创建用户和组:使用useradd和groupadd命令创建新用户和新组。2、修改用户和组信息:使用usermod和groupmod命令来修改用户和组的信息。3、删除用户和组:使用userdel和groupdel命令来删除用户和组。......
  • 2024年,AI驱动测试管理工具会有哪些发展前景呢?
    随着人工智能技术的日新月异,2024年的测试管理工具将迎来全新的发展机遇。AI赋能将助力测试管理工具实现前所未有的智能化升级,为软件研发团队带来革命性的变革。一、什么是AI?人工智能(AI)是一种能够模仿人类智能行为的技术。它通过模拟人类大脑的功能来解决复杂问题,具有学习、......
  • 深入Linux内核架构 (莫尔勒(Wolfgang Mauerer))-学习笔记
    书:pan.baidu.com/s/1qLSqtZPkRpflXrwcBOeUAQ?pwd=b2y3我的阅读笔记:Linux内核概述: 介绍Linux内核的基本结构、组成部分以及内核的主要功能。涵盖内核空间和用户空间之间的界限,以及内核如何管理系统资源。进程管理: 探讨Linux中进程的创建、调度、执行和终止。包括进程控制块......
  • VMware ESXi 8.0U3 macOS Unlocker & OEM BIOS ConnectX-3 网卡定制版 (集成驱动版)
    VMwareESXi8.0U3macOSUnlocker&OEMBIOSConnectX-3网卡定制版(集成驱动版)VMwareESXi8.0U3macOSUnlocker&OEMBIOS集成网卡驱动和NVMe驱动(集成驱动版)发布ESXi8.0U3集成驱动版,在个人电脑上运行企业级工作负载请访问原文链接:https://sysin.org/blog/vmwa......
  • 嵌入式Linux中的LED驱动控制(设备树方式)
    Linux3.1之后的内核版本,引入了设备树的概念。同时,设备树还需要Bootloader的支持,如果使用Uboot,在1.1.3版本之后就可以支持设备树了。设备树概念的提出其实有两方面的原因。其一当然是代码冗余,导致Linux内核臃肿不堪。在Linux内核源码中,只要是通过了基金会的认可,就可以把某个厂商的......
  • Linux源码阅读笔记08-进程调度API系统调用案例分析
    kthread_create_on_nodekthread_create_on_node函数功能:指定存储节点创建新内核线程。源码如下:操作实战#include<linux/module.h>#include<linux/pid.h>#include<linux/sched.h>#include<linux/kthread.h>#include<linux/wait.h>intMyThreadFunc(void*......
  • python解析Linux top 系统信息并生成动态图表(pandas和matplotlib)
    文章目录0.引言1.功能2.使用步骤3.程序架构流程图结构图4.数据解析模块5.图表绘制模块6.主程序入口7.总结8.附录完整代码0.引言在性能调优和系统监控中,top命令是一种重要工具,提供了实时的系统状态信息,如CPU使用率、内存使用情况和进程状态。然而,仅凭......
  • 【Linux系列】修改ssh端口
    #Linux#等保场景:在CentOS7.9操作系统上,修改默认的ssh端口。ssh默认22端口,在实际开展业务中的生产环境中,通常会修改为指定端口号,以满足规范。版本:CentOS7.91.修改sshd_config配置文件修改命令:vi/etc/ssh/sshd_config修改内容:Port100222.重启sshd服务3.查看端口信息......
  • Linux升级软件系统,防止其他用户登录影响升级,可以进行的操作
    题目解析touch/etc/nolgoin:禁止所有普通用户登录iptable-sINPUT-ttcp-s!127.0.0.1-jDROP:屏蔽非127.0.0.1请求;Linux的七个运行级别Linux下的7个运行级别:0:系统停机状态,系统默认运行级别不能设置为0,否则不能正常启动,机器关闭。1:单用户工作状态,root权限,用于系统......
  • Linux简史看这篇就够了
    目录一、Unix操作系统1、为什么要讲Unix?2、Unix发展史2.1、早期计算机存在的问题2.2、CTSS系统诞生2.3、Multics计划2.4、Unics诞生2.5、Unix系统诞生2.6、Unix版权宣告2.7、Minix系统诞生二、Linux操作系统1、Linux系统起源2、GNU计划3、Linux版本的衍生版本3.......