#include<linux/init.h>
#include<linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/poll.h>
struct cdev* cdev;
struct device* dev;
struct class* cls;
int major=0;
int minor=0;
const int countt=1;
#define LNAME "meleds"
char kbuf[128]={0};
wait_queue_head wq;
int condition=0;
ssize_t myy_read(struct file *file, char __user *ubuf, size_t size, loff_t * offs)
{
int ret;
if(size > sizeof(kbuf))
{
size=sizeof(kbuf);
}
ret=copy_to_user(ubuf,kbuf,size);
if(ret)
{
printk("copy to user error\n");
return -EIO;
}
condition=0;
return size;
}
ssize_t myy_write(struct file *file, const char __user *ubuf, size_t size, loff_t * offs)
{
int ret;
if(size > sizeof(kbuf))
{
size=sizeof(kbuf);
}
ret=copy_from_user(kbuf,ubuf,size)
if(ret)
{
printk("copy from user error\n");
return -EIO;
}
wake_up_interruptible(&wq);
condition=1;
return size;
}
int myy_open(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
int myy_close(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
__poll_t myy_poll(struct file *file, struct poll_table_struct * wait)
{
__poll_t mask=0;
poll_wait(file,&wq,wait);
if(condition)
{
mask |= EPOLLIN;
}
return mask;
}
const struct file_operations fops={
.open=myy_open,
.release=myy_close,
.read=myy_read,
.write=myy_write,
.poll=myy_poll,
};
static int __init ioduolu_init(void)
{
int i,ret;
dev_t devno;
cdev=cdev_alloc();
if(cdev == NULL)
{
printk("cdev error\n");
ret=-ENOMEM;
goto ERR1;
}
cdev_init(cdev,&fops);
ret=alloc_chrdev_region(devno,minor,countt,LNAME);
if(ret)
{
printk("alloc error\n");
goto ERR2;
}
major=MAJOR(devno);
minor=MINOR(devno);
ret=cdev_add(cdev,MKDEV(major,minor),countt)
if(ret)
{
printk("cdev add error\n");
goto ERR3;
}
cls=class_create(THIS_MODULE,LNAME);
if(IS_ERR(cls))
{
printk("class error\n");
ret=PTR_ERR(cls);
goto ERR4;
}
dev=device_create(cls,NULL,MKDEV(major,minor),NULL,"myledss",i);
if(IS_ERR(dev))
{
printk("dev error\n");
ret=PTR_ERR(dev);
goto ERR5;
}
init_waitqueue_head(&wq);
return 0;
ERR5:
device_destroy(cls,MKDEV(major,minor));
class_destroy(cls);
ERR4:
cdev_del(cdev);
ERR3:
unregister_chrdev_region(MKDEV(major,minor),countt);
ERR2:
kfree(cdev);
ERR1:
return ret;
}
static void __exit ioduolu_exit(void)
{
device_destroy(cls,MKDEV(major,minor));
class_destroy(cls);
cdev_del(cdev);
unregister_chrdev_region(MKDEV(major,minor),countt);
kfree(cdev);
}
module_init(ioduolu_init);
module_exit(ioduolu_exit);
MODULE_LICENSE("GPL")
关于IO多路复用的字符设备驱动(自我记录)
最新推荐文章于 2024-10-07 01:23:40 发布