1、定义LED设备结构体,成员变量为设备的相关属性
2、定义file_operations 操作集,完成open,read,write,release函数
3、加载驱动时,完成设备注册和自动创建设备节点
字符设备注册方法:先创建设备号,再初始化cdev,再添加cdev
自动创建设备节点:先创建类,再创建设备
4、卸载驱动时,依次进行以下操作
删除字符设备,注销设备号,摧毁设备,摧毁类
#define NEWCHRLED_NAME "newchrled"
#define NEWCHRLED_COUNT 1
/*LED 设备结构体*/
struct newchrled_dev
{
struct cdev cdev; /*字符设备*/
dev_t devid; /*设备号*/
struct class *class; /*类*/
struct device *device; /*设备*/
int major; /*主设备号*/
int minor; /*此设备号*/
};
struct newchrled_dev newchrled; /*led 设备*/
static int newchrled_open(struct inode *inode, struct file *filp)
{
filp->private_data = &newchrled;
return 0;
}
static int newchrled_release(struct inode *inode, struct file *filp)
{
struct newchrled_dev *dev = (struct newchrled_dev*)filp->private_data;
return 0;
}
static ssize_t newchrled_write(struct file *filp, const char __user *buf,
size_t count, loff_t *ppos)
{
int retvalue;
struct newchrled_dev *dev = (struct newchrled_dev*)filp->private_data;
return 0;
}
static const struct file_operations newchrled_fops={
.owner = THIS_MODULE,
.write = newchrled_write,
.open = newchrled_open,
.release= newchrled_release,
};
/*入口*/
static int __init newchrled_init(void)
{
int ret = 0;
unsigned int val = 0;
printk("newchrled_init\r\n");
/********新的字符设备注册方法,先创建设备号,再初始化cdev,再添加cdev***********/
/*注册字符设备*/
/* 1、创建设备号 */
newchrled.major=0; /*设置为0,表示由系统申请设备号*/
if (newchrled.major)/*给定主设备号*/
{
newchrled.devid = MKDEV(newchrled.major,0);
ret = register_chrdev_region(newchrled.devid, NEWCHRLED_COUNT, NEWCHRLED_NAME);
}
else /*没有给定主设备号*/
{
ret = alloc_chrdev_region(&newchrled.devid,0, NEWCHRLED_COUNT,NEWCHRLED_NAME);
newchrled.major =MAJOR(newchrled.devid);
newchrled.minor =MINOR(newchrled.devid);
}
if(ret<0)
{
printk("newchrled chrdev_region err!\r\n");
goto fail_devid;
}
printk("newchrled major = %d,minor=%d\r\n",newchrled.major,newchrled.minor);
/* 2、初始化 cdev */
newchrled.cdev.owner = THIS_MODULE;
cdev_init(&newchrled.cdev,&newchrled_fops);
/* 3、添加一个 cdev */
ret= cdev_add(&newchrled.cdev, newchrled.devid, NEWCHRLED_COUNT);
if(ret<0)
{
goto fail_cdev;
}
/********加载驱动时,自动创建设备节点,先创建类,再创建设备***********/
/* 4、创建类 */
newchrled.class = class_create(THIS_MODULE,NEWCHRLED_NAME);
if (IS_ERR(newchrled.class))
{
ret = PTR_ERR(newchrled.class);
goto fail_class;
}
/*5.创建设备*/
newchrled.device = device_create(newchrled.class, NULL,
newchrled.devid, NULL, NEWCHRLED_NAME);
if (IS_ERR(newchrled.device))
{
ret=PTR_ERR(newchrled.device);
goto fail_device;
}
return 0;
fail_device:
class_destroy(newchrled.class);
fail_class:
cdev_del(&newchrled.cdev);
fail_cdev:
unregister_chrdev_region(newchrled.devid, NEWCHRLED_COUNT);
fail_devid:
return ret;
}
/*出口函数*/
static void __exit newchrled_exit(void)
{
unsigned int val = 0;
/*1、删除字符设备*/
cdev_del(&newchrled.cdev);
/*2、注销设备号*/
unregister_chrdev_region(newchrled.devid, NEWCHRLED_COUNT);
/*3、摧毁设备*/
device_destroy(newchrled.class, newchrled.devid);
/*4、摧毁类*/
class_destroy(newchrled.class);
}
/*注册和卸载驱动*/
module_init(newchrled_init);
module_exit(newchrled_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("supersmart");