#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
/*声明设备文件操作的打开、读写、关闭基本操作*/
/*定义这些函数与file_operations中的函数指针相对应*/
ssize_t chr_drv_read(struct file *filep, char __user *buffer, size_t sizet, loff_t *lofft);//从设备中同步读取数据
ssize_t chr_drv_write(struct file *filep, const char __user *buffer, size_t sizet, loff_t *lofft);//向设备发送数据
int chr_drv_open(struct inode *inodep, struct file *filep); //打开
int chr_drv_close(struct inode *inodep, struct file *filep); //关闭
struct device *dev;
struct class *devclass;
static unsigned int dev_major = 270;//指静态指定设备号为280
//user instructions "cat /proc/devices" to view all devices and devices major
const struct file_operations my_fops={ //文件io接口结构体,以实现open
//read,write的操作
.open = chr_drv_open, /*把函数chr_drv_open赋值给指定.open*/
/*使用用户的程序open与设备驱动的open关联起来,用 .open 实现关联*/
.read = chr_drv_read, /*把函数chr_drv_read赋值给指定.read*/
.write = chr_drv_write, /*把函数chr_drv_write赋值给指定.write*/
.release = chr_drv_close, /*把函数chr_drv_close赋值给指定.close*/ /*关闭驱动文件*/
};
static int kernel_val =555;
//read(fd,buffer,count);
/*设备文件的打开、读写、关闭*/
ssize_t chr_drv_read(struct file *filep,char __user *buffer,size_t sizet,loff_t *lofft)
{
int ret;
printk("-------------------%s---------------------\n",__FUNCTION__);
ret=copy_to_user(buffer,&kernel_val,4);//kernel give data to user
if(ret > 0){
printk("\nKERNEL: read failed.\n");
return -EFAULT;
}
return 0;
}
//write(fd,buf,count);
ssize_t chr_drv_write(struct file *filep, const char __user *buffer, size_t sizet, loff_t *lofft)
{
int value;
int ret;
//printk("-------------------%s---------------------\n",__FUNCTION__);
ret=copy_from_user(&value,buffer,4);
if(ret > 0){
printk("\nwrite to KERNEL failed.\n");
return -EFAULT;
}
printk("\nI am KERNEL: value=%d\n",value);
return 0;
}
int chr_drv_open(struct inode *inmodep, struct file *filep)
{
printk("-------------------%s---------------------\n",__FUNCTION__);
return 0;
}
int chr_drv_close(struct inode *inodep, struct file *filep)
{
printk("-------------------%s---------------------\n",__FUNCTION__);
return 0;
}
static int __init chr_drv_init(void)
{
#if 1
int ret;//设备号的返回值
//静态申请设备号
ret=register_chrdev(dev_major,"chr_drv_test",&my_fops);
if(ret == 0){//设备号申请成功,返回值为0
printk("register successful.\n");
//mknod /dev/chr0 c dev_major 0;
}
else
{
printk("register fauled.\n");
return -EFAULT; //申请失败,返回错误码,错误码为一个负数
//或者写成 return -EINVAL
}
#endif
#if 2
//自动创建设备节点
devclass = class_create(THIS_MODULE,"chrar2_dev");
dev = device_create(devclass,NULL,MKDEV(dev_major,0),NULL,"char2");//第3个参数 MKDEV(dev_major,0)
//表示主设备号由 dev_major 指定,次设备号为0, 宏
//MKDEV 在目录\include\uapi\linux中定义的头文件 kdev_t.h 中指定
printk("auto create the nod successful.\n");
#endif
return 0;
}
static void __exit chr_drv_exit(void)
{
#if 2//销毁动态创建的设备号
device_destroy(devclass,MKDEV(dev_major,0));//先销毁由
//device_create创建的设备
class_destroy(devclass);//再销毁由class_create函数创建的类
printk("device delet successful.\n");
#endif
#if 1 //销毁静态创建的设备号
unregister_chrdev(dev_major,"chr_drv_test"); /*在模块卸载时释放设备号*/
printk("device delet successful.\n");
#endif
}
module_init(chr_drv_init);
module_exit(chr_drv_exit);
MODULE_LICENSE("GPL");