Linux驱动学习记录-18.MISC的LED驱动

misc的意思是混杂的,因此叫做混杂驱动。MISC驱动是最简单的字符设备驱动,通常嵌套在platform总线驱动里。

一、MISC驱动简介

1.结构体

所有MISC驱动的主设备号都是10,不同的设备使用不同的次设备号。MISC会自动创建cdev,不用像之前一样手动创建。因此只要向Linux注册一个miscdevice设备,定义在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;
};

我们关心的成员主要是前三个:

  • minor:测设备号
  • *name:设备名字
  • *fops:设备函数操作集
    预定义的次设备号在结构体上面,使用MISC的时候从上面已定义的次号选择一个,自己也可添加设备号。

2.使用

当设置好miscdevice后,需要使用misc_register向内核注册MISC设备。移除时,用misc_deregister来注销设备。

int misc_register(struct miscdevice *misc)
//成功返回0,失败返回负数
int misc_deregister(struct miscdevice *misc)
//成功返回0,失败返回负数

而不用像以前一样,调用一大堆函数来注册注销。

二、LED驱动程序

采用设备树platform总线方式下的MISC的led驱动。程序框架如下:

1.MISC设备结构体

相比于从前,MISC驱动少了主、此设备号的成员,因为主设备号默认10,次设备号在预定义里。

struct miscled_dev{
	dev_t devid;
	struct cdev cdev;
	struct calss *calss;
	struct device *device;
	struct device_node *nd;
	int led_gpio;
};
struct miscled_dev miscled;

2.开、写等操作函数,以及函数集

static int miscled_open(struct inode *inode, struct file *filp)
{
	filp->peivate_data = &miscled;
	return 0;
}

static ssize_t miscled_write(struce file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
	int retvalue;
	unsigned cahr databuf[1];
	unsigned char ledstate;
	struct miscled_dev *dev = filp->peivate_data;

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

	if(ledstate == LEDON){
		gpio_set_value(dev->led_gpio, 0);
	} else if(ledstate == LEDOFF){
		gpio_set_value(dev->led_gpio, 1);
	}
	return 0;
}

static sturt file_operations miscled_fops = {
	.owner = THINS_MODULE,
	.open = miscled_open,
	.write = miscled_write,
};

3.MISC驱动结构体

#define MISCLED_NAME "miscled"
#define MISCLED_MINOR 144

static struct miscdevice miscled_dev = {
	.minor = MISCLED_MINOR,
	.name = MISCLED_NAME,
	.fops = miscled_fops,
};

4.probe和remov函数、匹配表以及platform结构体

static int miscled_probe(struct platform_device *dev)
{
	int ret = 0;
	ret = misc_register(&miscled_dev); //注册misc设备,输入结构体地址

	miscled.nd = of_find_node_by_path("/led");

	miscled.led_gpio = of_get_named_gpio(miscled.nd, "led-gpio", 0);

	gpio_request(miscled.led_gpio, "miscled");
	gpio_direction_output(miscled.led_gpio, 1);

	return 0;
}

static int miscled_remove(struct platform_device *dev)
{
	gpio_set_value(miscled.led_gpio, 1);
	misc_deregister(&miscled_dev); //注销misc设备
	return 0;
}
/*匹配列表*/
static const struct of_device_id led_of_match[] = {
	{ .compatible = "gpio-led" },
	{ /*Sentinel*/ }
};
static struct platform_device miscled_driver = {
	.driver = {
		.name = "imx6ul-led", //驱动名字,加载成功会在/sys/bus/platform/drivers目录下存一个“imx6ul-led”的文件,用于和platform设备的name匹配。
		.of_math_table = led_of_match,
	},
	.probe = miscled_probe,
	.remove = miscled_remove,
};

5.出口入口函数以及最后的定义

static int __init miscled_init(void)
{
	return platform_driver_register(&miscled_driver);
}
static void __exit miscled_exit(void)
{
	platform_driver_unregister(&miscled_driver);
}

module_init(miscled_init);
module_exit(led_eximiscled_exitt);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gordon");

三、测试编译

进入/sys/class/misc/可以看到对应的MISC设备文件。
驱动和设备匹配成功后会生成/dev/miscled这个设备驱动文件。
测试驱动直接用设备树led的应用程序即可。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值