#include <linux/kernel.h> #include <linux/fs.h> #include <linux/module.h> #include <linux/init.h> #include <linux/device.h> #include <linux/ctype.h> #include <linux/cdev.h> #include <linux/major.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/kdev_t.h> #include <linux/mm.h> #include <linux/slab.h> #include <asm/uaccess.h>
MODULE_LICENSE("GPL"); #define
COMMAND1 1 #define COMMAND2 2 struct DEMO_dev{ struct cdev cdev ; char name [10]; }*DEMO_devp;
static dev_t DEMO_dev_number; static unsigned char file_inc = 0; static u8 demoBuffer[256]; struct class *DEMO_class;
#define
DEVICE_NAME "DEMO"
static void __exit DEMO_cleanup(void){
cdev_del(&DEMO_devp->cdev);
device_destroy(DEMO_class,MKDEV(
MAJOR(DEMO_dev_number),0)); class_destroy(DEMO_class);
printk("DEMO
clean up\n"); return ; } static int DEMO_open(struct
inode *inode,struct file*
file){ struct DEMO_dev *dev; if(file_inc>0) return -ERESTARTSYS; file_inc
++; dev
= container_of(inode->i_cdev,struct
DEMO_dev,cdev); file->private_data = dev; return 0; }
static int DEMO_release(struct
inode *inode,struct file *fp){ file_inc--; return 0; }
static ssize_t DEMO_read(struct
file *fp,
char __user *buf, size_t count,
loff_t *f_pos){ loff_t
pos = *f_pos; if(pos >= 256){ return 0; } if(count
> (256-pos)){ count = 256 -
pos; } pos
+= count;
if(copy_to_user(buf,demoBuffer+*f_pos,count)){ count=-EFAULT; return count; } *f_pos = pos; return count; } static ssize_t DEMO_write(struct
file *fp,const
char __user *buf, size_t count,
loff_t *f_pos){ size_t retval = -ENOMEM; loff_t
pos = *f_pos;
if(pos>=256){ return retval; } if(count>(256-pos)){ count=256-pos; } pos+=count;
if(copy_from_user(demoBuffer+*f_pos,
buf, count)){ retval
= -EFAULT; return retval; } *f_pos=pos; return count; }
loff_t DEMO_llseek(struct file*
fp,loff_t off, int where){ loff_t
pos; pos=fp->f_pos; switch(where){ case 0: pos =
off; break; case 1: pos+=off; break; case 2: default: return -EINVAL; } if((pos>256)||(pos<0)){ return -EINVAL; } return fp->f_pos=pos; } int DEMO_ioctl(struct
inode* inode, struct file *fp,
unsigned int cmd, unsigned long arg){ if(cmd==COMMAND1){ printk("ioctl command1 trigger\n"); return 0; } if(cmd==
COMMAND2){ printk("ioctl command2 trigger\n"); } printk("ioctl error\n"); return -EFAULT; } static struct file_operations DEMO_fops = { .owner = THIS_MODULE, .open =
DEMO_open, .release = DEMO_release, .read =
DEMO_read, .write =
DEMO_write, .llseek = DEMO_llseek, .ioctl = DEMO_ioctl, };
static int __init DEMO_init(void){
if(0 > alloc_chrdev_region(&DEMO_dev_number,0,1,DEVICE_NAME)){ printk(KERN_DEBUG"Can't register device\n"); return -1; }
DEMO_class
= class_create(THIS_MODULE,DEVICE_NAME);
DEMO_devp
= kmalloc(sizeof(struct
DEMO_dev),GFP_KERNEL); if(!DEMO_devp){ printk("Bad
Kmalloc\n"); return -ENOMEM; }
sprintf(DEMO_devp->name,"DEMO");
cdev_init(&DEMO_devp->cdev,&DEMO_fops);
DEMO_devp->cdev.owner = THIS_MODULE; DEMO_devp->cdev.ops =
&DEMO_fops;
if(cdev_add(&DEMO_devp->cdev,DEMO_dev_number,1)){ printk
("Bad cdev\n"); return 1; }
device_create(DEMO_class,NULL,DEMO_dev_number,NULL,"DEMO");
printk("DEMO
device initialized\n"); return 0; } module_init(DEMO_init); module_exit(DEMO_cleanup);
|