#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/security.h>
#define MRY_MAJOR 100
#define uint unsigned int
#define ulong unsigned long
static int mry_major=MRY_MAJOR;
typedef struct
{
struct cdev dev;
//add private data
}mry_dev;
mry_dev *_pdev;
int mry_open(struct inode *pinode,struct file *pfile)
{
pfile->private_data=_pdev;
return 0;
}
int mry_release(struct inode *pinode,struct file *pfile)
{
return 0;
}
static int mry_ioctl(struct inode *pinode,struct file *pfile,uint cmd,ulong arg)
{
mry_dev *pdev=pfile->private_data;
switch(cmd)
{
case 1:break;
default:
return -EINVAL;
}
return 0;
}
static int mry_read(struct file *pfile,char __user *buf,size_t size,loff_t *ppos)
{
ulong p=*ppos;
uint count=size;
int rs=0;
mry_dev *pdev=pfile->private_data;
#if 0
if(copy_to_user(buf,(void*)(pdev->mem+p),count)
{
rs=-EFAULT;
}
else
{
*ppos+=count;
rs=count;
printk(KERN_INFO "read %d bytes from %d\n",count,p);
}
#endif
return rs;
}
static int mry_write(struct file *pfile,const char __user *buf,size_t size,loff_t *ppos)
{
ulong p=*ppos;
uint count=size;
int rs=0;
mry_dev *pdev=pfile->private_data;
#if 0
if(copy_from_user(pdev->mem+p,buf,count)
{
rs=-EFAULT;
}
else
{
*ppos+=count;
rs=count;
printk(KERN_INFO "write %d bytes from %d\n",count,p);
}
#endif
return rs;
}
static const struct file_operations _fops=
{
.owner=THIS_MODULE,
.read=mry_read,
.write=mry_write,
.ioctl=mry_ioctl,
.open=mry_open,
.release=mry_release,
};
static void mry_setup_cdev(mry_dev *pdev,int index)
{
int err,devno=MKDEV(mry_major,index);
cdev_init(&pdev->dev,&_fops);
pdev->dev.owner=THIS_MODULE;
pdev->dev.ops=&_fops;
err=cdev_add(&pdev->dev,devno,1);
if(err)
printk(KERN_NOTICE "Error %d adding LED %d",err,index);
}
int mry_init(void)
{
int rs;
dev_t devno=MKDEV(mry_major,0);
if(mry_major)
rs=register_chrdev_region(devno,1,"mrydriver");
else
{
rs=alloc_chrdev_region(&devno,0,1,"mrydriver");
mry_major=MAJOR(devno);
}
if(rs<0){
return rs;
}
_pdev=kmalloc(sizeof(mry_dev),GFP_KERNEL);
if(!_pdev)
{
rs=-ENOMEM;
goto fail_malloc;
}
memset(_pdev,0,sizeof(mry_dev));
mry_setup_cdev(_pdev,0);
printk(KERN_INFO "mry driver ok");
return 0;
fail_malloc:
printk(KERN_INFO "failed");
unregister_chrdev_region(devno,1);
return rs;
}
void mry_exit(void)
{
cdev_del(&_pdev->dev);
kfree(_pdev);
unregister_chrdev_region(MKDEV(mry_major,0),1);
}
MODULE_AUTHOR("MrY");
MODULE_LICENSE("Dual BSD/GPL");
module_param(mry_major,int,S_IRUGO);
module_init(mry_init);
module_exit(mry_exit);
|