Linux驱动开发9 LinuxMISC 驱动(杂项驱动)

内核自带的驱动,都是通过图形化界面配置,选择使能或者不使用

 

	/* zuozhongkai dts leds linux自带led驱动的设备树
		这个是linux自带的驱动,一定要注意
		你只需要添加设备树,添加设备信息即可
		一定要注意添加的compatible属性名与linux自带的led驱动属性名相同

	*/
    dtsleds {
        compatible = "gpio-leds"; //
 
        led0 {
            label = "red";
            gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
            linux,default-trigger = "heartbeat";
            default-state = "on";
        };
    };

MISC 驱动(杂项驱动)

MISC 驱动其实就是最简单的字符设备驱动,通常嵌套在 platform 总线驱动中,实现复杂的驱动
所有的 MISC 设备驱动的主设备号都为 10,MISC 设备会自动创建 cdev,不需要像我们以前那样手动创建,因此采用 MISC 设备驱动可以简化字符设备驱动的编写。我们需要向 Linux 注册一个 miscdevice 设备,miscdevice是一个结构体,定义在文件 include/linux/miscdevice.h 中
需要设置 minor name fops 这三个成员变量
1、minor 表示子设备号, MISC 设备的主设备号为 10 ,这个是固定的,需要用户指定子设备号,Linux 系统已经预定义了一些 MISC 设备的子设备号,这些预定义的子设备号定义在 include/linux/miscdevice.h 文件中
2、name 就是此 MISC 设备名字,当此设备注册成功以后就会在/dev 目录下生成一个名为 name
的设备文件。
3、 fops 就是字符设备的操作集合
一、当设置好 miscdevice 以后就需要使用 misc_register 函数向系统中注册一个 MISC 设备, 代替原来的设备创建驱动操作流程

二、卸载设备驱动模块的时候需要调用 misc_deregister 函数来注销掉 MISC 设备, 代替原来的注销设备驱动操作流程

 

 

//设备树
beep {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "atkalpha-beep";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_beep>;
		beep-gpio = <&gpio5 1 GPIO_ACTIVE_HIGH>;
		status = "okay";
	};
#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>

/***************************************************************

Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.

文件名		: miscbeep.c

作者	  	: 左忠凯

版本	   	: V1.0

描述	   	: 采用MISC的蜂鸣器驱动程序。

其他	   	: 无

论坛 	   	: www.openedv.com

日志	   	: 初版V1.0 2019/8/20 左忠凯创建

***************************************************************/

#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设备 */



/*

 * @description		: 打开设备

 * @param - inode 	: 传递给驱动的inode

 * @param - filp 	: 设备文件,file结构体有个叫做private_data的成员变量

 * 					  一般在open的时候将private_data指向设备结构体。

 * @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 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设备结构体需要设置 minor、name 和 fops 这三个成员变量*/

static struct miscdevice beep_miscdev = {

	.minor = MISCBEEP_MINOR,

	.name = MISCBEEP_NAME,

	.fops = &miscbeep_fops,

};

//

 /*

  * @description     : flatform驱动的probe函数,当驱动与

  *                    设备匹配以后此函数就会执行

  * @param - dev     : platform设备

  * @return          : 0,成功;其他负值,失败

  */

static int miscbeep_probe(struct platform_device *dev)

{

	/*1\初始化蜂鸣器IO*/

	int ret = 0;



	// 亦可使用 miscbeep.nd = dev->dev.of_node 直接获取设备节点

	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设备驱动即可

	   misc驱动注册  misc_register 函数

	 */

	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;

}

//

 /* 这又是platform平台那一套(有设备树) */

 /* 匹配列表 */

 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,

};



//

/*

 * @description	: 驱动出口函数

 * @param 		: 无

 * @return 		: 无

 */

static int __init miscbeep_init(void)

{

	return platform_driver_register(&beep_driver);

}



/*

 * @description	: 驱动出口函数

 * @param 		: 无

 * @return 		: 无

 */

static void __exit miscbeep_exit(void)

{

	platform_driver_unregister(&beep_driver);

}



module_init(miscbeep_init);

module_exit(miscbeep_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("wuhaozhen");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值