文章目录
- 前言
- 一、misc是什么?
- 二、调用API
- 1.注册
- 2.注销
- 三、驱动框架
- 总结
前言
misc设备即杂项设备,Linux系统中类似按键、触摸屏都有专门框架处理,类似adc、蜂鸣器等设备无法明确其属于什么类型,一般就归属于杂项设备,按misc驱动框架编写驱动程序。
一、misc是什么?
所有的 MISC 设备驱动的主设备号都为 10,不同的设备使用不同的从设备号。为了解决字符设备驱动的不断增加。MISC设备会自动创建cdev,我们需要向Linux注册一个miscdevice设备,是一个结构体,定义在文件 include/linux/miscdevice.h 中:
struct miscdevice {
int minor; // 次设备号
const char *name; // 设备名字 /dev目录下生成设备文件
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_DYNAMIC_MINOR
也可以在 include/linux/miscdevice.h 中选,也可以自己定义,只要没被使用
二、调用API
1.注册
函数如下:
int misc_register(struct miscdevice * misc)
misc:要注册的 MISC 设备。
返回值: 负数,失败; 0,成功
可以代替以前字符驱动的这些步骤:
alloc_chrdev_region(); /* 申请设备号 */
cdev_init(); /* 初始化 cdev */
cdev_add(); /* 添加 cdev */
class_create(); /* 创建类 */
device_create(); /* 创建设备 */
2.注销
函数如下:
int misc_deregister(struct miscdevice *misc)
misc:要注销的 MISC 设备。
返回值: 负数,失败; 0,成功。
可以代替以前字符驱动的这些步骤:
cdev_del(); /* 删除 cdev */
unregister_chrdev_region(); /* 注销设备号 */
device_destroy(); /* 删除设备 */
class_destroy(); /* 删除类 */
三、驱动框架
下面展示一个基本的misc驱动框架示例
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
struct myled_data {
struct miscdevice mdev;
int gpio;
};
struct myled_data myled;
int led_open (struct inode *a, struct file *b)
{
return 0;
}
ssize_t led_write(struct file *a, const char __user *b, size_t c, loff_t *d)
{
char buf[5] = {0};
int ret = 0;
ret = copy_from_user(buf,b,c);
if(ret < 0)
{
printk("misc led failed to copy_from_user\n");
return -EFAULT;
}
if(buf[0] == 0)
gpio_set_value(myled.gpio,0);
else
gpio_set_value(myled.gpio,1);
return ret;
}
struct file_operations fop =
{
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
};
int led_probe(struct platform_device *pdev)
{
int ret = 0;
myled.gpio = of_get_named_gpio(pdev->dev.of_node,"led-gpio",0);
ret = devm_gpio_request(&pdev->dev,myled.gpio,"LED GPIO");
if(ret)
{
dev_err(&pdev->dev,"devm_gpio_request failed !\n");
return ret;
}
gpio_direction_output(myled.gpio,0);
myled.mdev.name = "misc_led";
myled.mdev.minor = MISC_DYNAMIC_MINOR; //动态分配
myled.mdev.fops = &fop;
return misc_register(&myled.mdev);
}
int led_exit(struct platform_device *pdev)
{
misc_deregister(&myled.mdev);
return 0;
}
struct of_device_id led_of_match[] = {
{.compatible = "misc_led"},
};
struct platform_driver myled_driver =
{
.driver = {
.name = "zynq_misc_led",
.of_match_table = led_of_match,
},
.probe = led_probe,
.remove = led_exit,
};
module_platform_driver(myled_driver);
MODULE_AUTHOR("LZW");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MISC DRIVER BASE ON MISC FRAMEWORK");
编写完ko成功加载后,即可在应用层像操作字符设备节点一样,进行open,read,write等操作。
总结
以上就是今天要讲的内容,本文简单介绍了misc设备驱动的编写及使用,制作不易,多多包涵。