/*
需要定义一个字符设备,里面有字符设备相关的方法
struct file_operations cdev_fops = {
.open = char_open, /*open方法*/
.release = char_release, /*close*/
.read = char_read,
.write = char_write,
.unlocked_ioctl = char_ioctl,
};
再附上我定义用来存储数据的结构体
struct gyo_struct{
struct device_node *of_node;
dev_t devno;
struct cdev cdev_obj;
struct class *cdev_cls;
struct device *cdev_device;
};
struct gyo_struct gyostruct;
*/
/*
申请设备号
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)
###dev_t *dev:dev_t 类型的参数 eg:dev_t devno 传参->&devno;
###unsigned baseminor:第一个次设备号,一般填0
###unsigned count:设备数量,按需要填,一个就写 1
###const char *name:设备名字,好像随便取,我也不知道去哪找~ eg:"char devno"
*/
ret = alloc_chrdev_region(&gyostruct.devno,0,1,"gyro devno");if(ret < 0){
printk("alloc_chrdev_region err%d\n",ret);
return -23;
}
/*
字符设备 创建对象,然后初始化该对象
void cdev_init(struct cdev *cdev, const struct file_operations *fops) /*初始化 属性 方法*/
###struct cdev *cdev:需要一个cdev类型的结构体,eg:struct cdev cdev_obj 传参->&m_cdev;
### const struct file_operations *fops:需要一个file_operations类型的结构体,里面存有属性和方法eg:struct file_operations cdev_fops 传参->&cdev_fops
int cdev_add(struct cdev p[], dev_t dev, unsigned count) /*将字符设备对象添加到内核*/
*/
cdev_init(&gyostruct.cdev_obj,&cdev_fops); /*初始化*/ret = cdev_add(&gyostruct.cdev_obj,gyostruct.devno,1); /*将我们之前获得设备号和设备号长度填充到cdev结构中*/
if(ret <0){
printk("%s->%d cdev_add err\n",__func__,__LINE__);
return -26;
}
/*
字符设备 第三步, 创建文件节点 在/sys/class/ 能找到class_create函数name的文件夹
#define class_create(owner, name)这是个宏,动态创建设备的逻辑类,并完成部分字段的初始化,然后将其添加到内核中
###owner:这是啥呀,我也不知道,一般都填的THIS_MODULE
###name:创建字符设备的文件节点,可以在/sys/class/找到
*/
gyostruct.cdev_cls = class_create(THIS_MODULE,"gyos char");if(!gyostruct.cdev_cls){
printk("%s->%d class_create \n",__func__,__LINE__);
return -29;
}
/*
设备节点的创建
struct device *device_create(struct class *class, struct device *parent,
dev_t devt, void *drvdata, const char *fmt, ...)
###struct class *class:要一个struct class类型的参数 eg:struct class *cls 传参->cls
###struct device *parent:爸爸指针吗,这个参数我也不知道耶,填个NULL
###dev_t devt:看下面我用的然后对照下结构体思考一下吧,我懒得想了
###void *drvdata:填NULL
###const char *fmt:自动创建,%d会自己顺序填,后面可以跟一个参数,表示起始号码,我填的0,所以会创建一个gyr0起始的设备节点,可以在/dev/里找到gyr0的文件
###...:从多少开始,就是前面的%d
*/
gyostruct.cdev_device =device_create(gyostruct.cdev_cls,NULL,gyostruct.devno,NULL,"gyro%d",0);
if(!gyostruct.cdev_device){
printk("%s->%d device_create \n",__func__,__LINE__);
return -30;
}
return 0;
}