linux字符设备驱动开发之MISC

misc 杂项驱动。
杂项驱动其实是字符设备驱动,嵌套在platform总线中,实现复杂的驱动。
当所使用外设无法分类,一般采用misc驱动。
misc驱动固定主设备号10,次设备号因不同设备不同。

misc驱动设备使用如下结构体描述:
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;
};

通过如下两个函数注册到内核:

extern int misc_register(struct miscdevice *misc);
extern int misc_deregister(struct miscdevice *misc);

相比于传统字符传统字符串设备,misc_register函数其实是实现了设备的注册+初始化功能;***misc_deregister***函数其实是实现了卸载模块+设备功能。
misc_register

alloc_chrdev_region(); /* 申请设备号 */
cdev_init(); /* 初始化 cdev */
cdev_add(); /* 添加 cdev */
class_create(); /* 创建类 */
device_create(); /* 创建设备 */

misc_deregister

cdev_del(); /* 删除 cdev */
unregister_chrdev_region(); /* 注销设备号 */
device_destroy(); /* 删除设备 */
class_destroy(); /* 删除类 */

misc 驱动框架 (在platform驱动中加入misc注册与卸载)

/* 设备结构体 */
struct xxx_dev{
struct cdev cdev;
/* 设备结构体其他具体内容 */
};

struct xxx_dev xxxdev; /* 定义个设备结构体变量 */

static int xxx_open(struct inode *inode, struct file *filp)
{
/* 函数具体内容 */
return 0;
}

static ssize_t xxx_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
/* 函数具体内容 */
return 0;
}
/*
 * 字符设备驱动操作集
*/
static struct file_operations xxx_fops = {
.owner = THIS_MODULE,
.open = xxx_open,
.write = xxx_write,
};

static struct miscdevice xxx_miscdev = {
.minor = ,	/*子设备号*/
.name = ,	/*名字*/
.fop = xxx_fop,
};


/*
* misc驱动的 probe 函数
* 驱动与设备匹配成功以后此函数就会执行
*/
static int xxx_probe(struct platform_device *dev)
{
......
/* 函数具体内容 */
misc_register(&xxx_miscdev);
return 0;
}

static int xxx_remove(struct platform_device *dev)
{
......
misc_unregister(&xxx_miscdev);
/* 函数具体内容 */
return 0;
}

/* 匹配列表 */
static const struct of_device_id xxx_of_match[] = {
{ .compatible = "xxx-gpio" },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, leds_of_match);
/*
* platform 平台驱动结构体
*/
static struct platform_driver xxx_driver = {
.driver = {
.name = "xxx",
.of_match_table = xxx_of_match,
},
.probe = xxx_probe,
.remove = xxx_remove,
};
/* 驱动模块加载 */
static int __init xxxdriver_init(void)
{
return platform_driver_register(&xxx_driver);
}
/* 驱动模块卸载 */
static void __exit xxxdriver_exit(void)
{
platform_driver_unregister(&xxx_driver);
}
module_init(xxxdriver_init);
module_exit(xxxdriver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("tom");

驱动加载成功,在 /sys/class/misc/ 中生成相应设备名称文件夹。

你可能感兴趣的:(linux驱动开发学习)