(Linux驱动学习 - 10).MISC驱动实验

news2024/12/28 19:39:50

一.MISC介绍

1.MISC定义

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

2.MISC特性

        ①.所有的 MISC 设备驱动的主设备号都为 10,不同的设备使用不同的从设备号。

        ②.MISC 设备驱动会自动创建 cdev ,因此 MISC 设备驱动编写可以简化字符设备驱动的编写。

     

二.MISC 设备驱动相关结构体与函数

1.miscdevice 结构体

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

2.注册一个 MISC 设备 -  misc_register

函数原型

/**
 * @description:            向系统注册一个 MISC 设备
 * @param - misc    :       要注册的 MISC 设备
 * @return          :       0成功,其他失败
 */
int misc_register(struct miscdevice *misc)

3.注销 MISC 设备 - misc_deregister

/**
 * @description:        注销 MISC 设备
 * @param - misc    :   要注销的 MISC 设备
 * @return          :   0成功,其他失败
 */
int misc_deregister(struct miscdevice *misc)

三.使用 platform 加 MISC 驱动框架编写 beep 蜂鸣器驱动

1.设备树部分

(1).流程图

(2).设备树代码

在 iomuxc 下添加pinctl

在根节点下添加 beep 节点

2.驱动部分

(1).流程图

(2).代码部分

#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 <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/fcntl.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.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;               /* cedv */
    struct class *class;            /* 类 */
    struct device *device;          /* 设备 */
    struct device_node *nd;         /* 设备结点 */
    int beep_gpio;                  /* beep 所使用的 GPIO 编号 */
};

struct miscbeep_dev miscbeep;       //beep 设备


/**
 * @description:            打开设备
 * @param - inode   :       传递给驱动的 inode
 * @param - filp    :       要打开的设备文件
 * @return          :       0成功,其他失败
 */
static int miscbeep_open(struct inode *inode,struct file *filp)
{
    /* 设置私有数据 */
    filp->private_data = &miscbeep; 

    return 0;
}


/**
 * @description:            向设备写数据
 * @param - filp    :       要打开的设备文件
 * @param - buf     :       要写入的数据
 * @param - cnt     :       要写入的字节数
 * @param - offt    :       相对于文件首地址的偏移量
 * @return          :       成功则返回(成功写入的字节数),失败则返回(负数)
 */
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 beep_state;

    struct miscbeep_dev *dev = filp->private_data;

    retvalue = copy_from_user(databuf,buf,cnt);
    if(0 > retvalue)
    {
        printk("kernel write failed!\r\n");
        return -EFAULT;
    }

    beep_state = databuf[0];
    if(BEEPON == beep_state)
    {
        gpio_set_value(dev->beep_gpio,1);       //打开蜂鸣器
    }
    else if(BEEPOFF == beep_state)
    {
        gpio_set_value(dev->beep_gpio,0);       //关闭蜂鸣器
    }

    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,
};




/**
 * @description:            platform 驱动的 probe 函数,当驱动与设备匹配以后会执行此函数
 * @param - dev     :       platform 设备
 * @return          :       0成功,其他失败
 */
static int miscbeep_probe(struct platform_device *dev)
{
    int ret = 0;

    printk("beep driver and device wa matched!\r\n");

    /* 一.初始化 BEEP 要使用的 GPIO */

    /* 1.获取设备结点 */
    miscbeep.nd = of_find_node_by_path("/beep");
    if(NULL == miscbeep.nd)
    {
        printk("beep node not find!\r\n");
        return -EINVAL;
    }

    /* 2.获取 BEEP 的 GPIO 编号 */
    miscbeep.beep_gpio = of_get_named_gpio(miscbeep.nd,"beep-gpio",0);
    if(0 > miscbeep.beep_gpio)
    {
        printk("can not get beep-gpio!\r\n");
        return -EINVAL;
    }

    /* 3.申请 gpio */
    gpio_request(miscbeep.beep_gpio,"beep");

    /* 4.初始化 gpio 为 高电平,即初始化关闭 BEEP */
    ret = gpio_direction_output(miscbeep.beep_gpio,1);
    if(0 > ret)
    {
        printk("can not set gpio!\r\n");
    }


    /* 二.注册 MISC 设备驱动 */
    ret = misc_register(&beep_miscdev);
    if(0 > ret)
    {
        printk("misc devie register failed!\r\n");
        return -EFAULT;
    }

    return 0;
}



/**
 * @description:            remove 函数
 * @param - dev     :       platform 设备
 * @return          :       0成功,其他失败
 */
static int miscbeep_remove(struct platform_device *dev)
{
    /* 关闭 BEEP */
    gpio_set_value(miscbeep.beep_gpio,1);

    /* 释放 BEEP 的 GPIO */
    gpio_free(miscbeep.beep_gpio);

    /* 注销 misc 设备驱动 */
    misc_deregister(&beep_miscdev);

    return 0;
}




/* 匹配列表 */
static const struct of_device_id beep_of_match[] = 
{
    {.compatible = "atkalpha-beep"},        //必须与设备树中属性匹配
    {}
};


/* platform 驱动结构体 */
static struct platform_driver beep_driver = 
{
    .driver = 
    {
        .name = "imx6ul-beep",              //驱动名字
        .of_match_table = beep_of_match,    //匹配列表
    },
    .probe = miscbeep_probe,
    .remove = miscbeep_remove,
};





/**
 * @description:            驱动入口函数
 * @param -         :       无
 * @return          :       无
 */
static int __init miscbeep_init(void)
{
    return platform_driver_register(&beep_driver);
}


/**
 * @description:            驱动出口函数
 */
static void __exit miscbeep_exit(void)
{
    return platform_driver_unregister(&beep_driver);
}


module_init(miscbeep_init);
module_exit(miscbeep_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("kaneki");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2211263.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能贴身监测,健康生活建议,圆道妙医智能手表体验

如今热衷于运动和健康生活的爱好者越来越多&#xff0c;相关的赛事等活动也是逐年增多&#xff0c;很多朋友为了能够直观的了解自己的健康状况&#xff0c;都会配备一款智能手表&#xff0c;这样戴在身上就可以随时了解自己的心率、血氧等数据。最近我尝试了一款圆道妙医推出的…

MobaXterm连接Cloudflare Tunnel内网穿透的SSH

背景 如官方文档所示&#xff0c;Cloudflare Tunnel要求我们对SSH客户端进行配置&#xff0c;使本地的cloudflared软件代理SSH才能连接。 存在问题 由于MobaXterm的Session实质为嵌入式PuTTY&#xff0c;不使用OpenSSH样式的配置文件&#xff08;即~/.ssh/config&#xff09…

SpringBoot框架下购物推荐网站的设计模式与实现

3系统分析 3.1可行性分析 通过对本东大每日推购物推荐网站实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本东大每日推购物推荐网站采用JAVA作为开发语言&…

对层级聚类树进行模块分割,定位基因在哪个模块中

拷贝数据到 ImageGP (http://www.ehbio.com/Cloud_Platform/front/#/analysis?pageb%27Ng%3D%3D%27)&#xff0c;并设置参数. ID untrt_N61311 untrt_N052611 untrt_N080611 untrt_N061011 trt_N61311 trt_N052611 trt_N080611 trt_N061011 ENSG000…

【ROS2实操二】服务通信

简介 服务通信也是ROS中一种极其常用的通信模式&#xff0c;服务通信是基于请求响应模式的&#xff0c;是一种应答机制。也即&#xff1a;一个节点A向另一个节点B发送请求&#xff0c;B接收处理请求并产生响应结果返回给A。比如如下场景&#xff1a;机器人巡逻过程中&#xff0…

cuda入门学习

最近接触cuda 编程&#xff0c;记录一下。 1 工作实现一个【0-100&#xff09;的加法 如果用python sum 0 for i in range(200):sumi print(sum)2 cuda 的一些简单的概念 一维情况下大概是这样的 (1个grid * 2个blocks * 4个thread) 3 代码直接上代码 我把100分为20个b…

Jenkins---01

什么是敏捷开发 敏捷开发以用户的需求进化为核心&#xff0c;采用迭代、循序渐进的方法进行软件开发。在敏捷开 发中&#xff0c;软件项目在构建初期被切分成多个子项目&#xff0c;各个子项目的成果都经过测试&#xff0c;具备可视、 可集成和可运行使用的特征。换言之&…

2024年编程资料【9月份部分】

资料列表 「CSDN会员免费电子书1000本」 https://pan.quark.cn/s/5019390a751a 【黑马程序员】年度钻石会员-人工智能AI进阶 https://pan.quark.cn/s/1d14a2a179c2 JavaScript从入门到高级教程 - 带源码课件 https://pan.quark.cn/s/c16ed07eac93 【马哥教育】云原生微服务治理…

测试常用插件: ModHeader - Modify HTTP headers插件进行IP模拟/IP欺骗

由于公司是做海外项目的&#xff0c;所以付款时有要求进行模拟不同IP登录进去时会优先显示该地区的支付方式。 1.安装插件 这里以Microsoft Edge为例&#xff0c;打开扩展 搜索&#xff1a;ModHeader - Modify HTTP headers&#xff0c;进行获取安装即可 安装完成后&#xff…

CVESearch部署、使用与原理分析

文章目录 前言1、概述2、安装与使用2.1、源码安装2.1.1、部署系统依赖组件2.1.1.1、下载安装基础组件2.1.1.2、下载安装MongoDB Community Edition 7.0 2.1.2、使用源码安装系统2.1.2.1、安装CVESearch2.1.2.2、填充MongoDB数据库2.1.2.3、填充Redis数据库 2.2、使用方法 3、测…

LeetCode | 704.二分查找

标准的二分查找&#xff0c;直接上模板&#xff01; class Solution(object):def search(self, nums, target):""":type nums: List[int]:type target: int:rtype: int"""l 0r len(nums) - 1while l < r:mid (l r 1) / 2if nums[mid] …

Telnet命令详解:安装、用法及应用场景解析

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

笔试算法总结

文章目录 题目1题目2题目3题目4 题目1 使用 StringBuilder 模拟栈的行为&#xff0c;通过判断相邻2个字符是否相同&#xff0c;如果相同就进行删除 public class Main {public static String fun(String s) {if (s null || s.length() < 1) return s;StringBuilder builde…

EventLoop模块 --- 事件循环模块

目录 1 设计思想 eventfd 创建eventfd 2 实现 3 联合调试 4 整合定时器模块 5 联合超时模块调试 1 设计思想 EventLoop 模块是和线程一一绑定的&#xff0c;每一个EventLoop模块内部都管理了一个Poller对象进行事件监控&#xff0c;同时管理着多个Connection对象&…

python 使用faker库 生成数据

Welcome to Faker’s documentation! — Faker 30.3.0 documentationVersion1: Example from docs:from faker import Faker from faker.providers import internet for i in range(2): #批量生成数据fake Faker()name fake.name()address fake.address()text f…

el-动态表单的校验不触发/只触发了部分项

参考&#xff1a; 深入了解Element Form表单动态验证问题 转载vue elementUI组件表单动态验证失效的问题与解决办法 在别人的代码上开发新功能时&#xff0c;发现动态表单的校验功能突然出现问题&#xff1a; 重构前,只有两步&#xff0c;通过type来判断当前显示内容 <el-f…

Cesium.js(SuperMap iClient3D for Cesium)进行三维场景展示和图层动画

1&#xff09;&#xff1a;参考API文档&#xff1a;SuperMap iClient3D for Cesium 开发指南 2&#xff09;&#xff1a;官网示例&#xff1a;support.supermap.com.cn:8090/webgl/Cesium/examples/webgl/examples.html#layer 3&#xff09;&#xff1a;SuperMap iServer&…

自定义类型 - 结构体

2024 - 10 - 13 - 笔记 - 26 作者(Author): 郑龙浩 / 仟濹(CSDN账号名) 自定义类型 - 结构体 平时用的数组是一组相同类型的数据&#xff0c;如果想表示一组不同类型的数据&#xff0c;那么就可以结构体了。 ① 结构体的声明&#xff08;重要&#xff09; 自己起的名字&…

[论文阅读]: Detecting Copyrighted Content in Language Models Training Data

发布链接&#xff1a;http://arxiv.org/abs/2402.09910 核心目标&#xff1a;检测语言模型的训练过程中是否使用了受版权保护的内容 基于假设&#xff1a;语言模型有可能识别训练文本中的逐字节选 工作&#xff1a;提出了 DE-COP&#xff0c;一种确定训练中是否包含受版权保…

如何在Android平板上使用谷歌浏览器进行网页缩放

在使用Android平板时&#xff0c;我们经常会浏览各种网页&#xff0c;但有时网页内容可能无法适应屏幕大小&#xff0c;这时就需要用到网页缩放功能。本文将为您详细介绍如何在Android平 板上的谷歌浏览器中进行网页缩放&#xff0c;帮助您更好地浏览网页。&#xff08;本文由h…