#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);
|