#define __NO_VERSION__
#include <linux/module.h>
#include <linux/config.h>
#include <linux/version.h>
#include <asm/uaccess.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <asm/segment.h>
#include <linux/ioctl.h>
#define SCULL_MAJOR 0
#define SCULL_MAGIC SCULL_MAJOR
#define SCULL_RESET _IO(SCULL_MAGIC,0)
#define SCULL_QUERY_NEW_MSG _IO(SCULL_MAGIC,1)
#define SCULL_QUERY_MSG_LENGTH _IO(SCULL_MAGIC,2)
#define IOC_NEW_MSG 1
unsigned int scull_major = 0;
struct Scull_Dev
{
void **data;
int quantum;
int qset;
unsigned long size;
unsigned int access_key;
unsigned int new_msg;
unsigned int usage;
struct Scull_Dev *next;
};
struct Scull_Dev scull;
int scull_open(struct inode *inode,struct file *filp)
{
MOD_INC_USE_COUNT;
printk("This chrdev is in open.\n");
return 0;
}
static ssize_t scull_write(struct file *file, const char *buf, size_t count, loff_t *f_pos)
{
printk("count:%d\n",count);
if(count<0)
return -EINVAL;
if(scull.usage||scull.new_msg)
return -EBUSY;
scull.usage=1;
kfree(scull.data);
scull.data=(char *)kmalloc(sizeof(char)*(count+1),GFP_KERNEL);
printk("have malloc for data!\n");
if(!scull.data)
{
return -ENOMEM;
}
copy_from_user(scull.data,buf,count+1);
scull.usage=0;
scull.new_msg=1;
return count;
}
static ssize_t scull_read(struct file *file,char *buf,size_t count,loff_t *f_pos)
{
int length;
if(count<0)
return -EINVAL;
if(scull.usage)
return -EBUSY;
scull.usage = 1;
if(scull.data == 0)
return 0;
length = strlen(scull.data);
if(length < count)
count = length;
copy_to_user(buf,scull.data,count + 1);
scull.new_msg = 0;
scull.usage = 0;
return count;
}
int scull_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
int ret=0;
switch(cmd)
{
case SCULL_RESET:
kfree(scull.data);
scull.data = NULL;
scull.usage = 0;
scull.new_msg = 0;
break;
case SCULL_QUERY_NEW_MSG:
if(scull.new_msg)
return IOC_NEW_MSG;
break;
case SCULL_QUERY_MSG_LENGTH:
if(scull.data == NULL)
{
return 0;
}
else
{
printk("scull.data:%d\n",strlen(scull.data));
return strlen(scull.data);
}
break;
default:
return -ENOTTY;
}
return ret;
}
void scull_release(struct inode *inode,struct file *filp)
{
MOD_DEC_USE_COUNT;
printk("This chrdev is in release!\n");
return;
#ifdef DEBUG
printk("scull_release(%p,%p)\n",inode,filp);
#endif
}
struct file_operations scull_fops = {
read:scull_read,
write:scull_write,
ioctl:scull_ioctl,
open:scull_open,
release:scull_release
};
int init_module()
{
int result=0;
printk("Hello! This is a testing module! \n");
result=register_chrdev(0,"scull",&scull_fops);
if(result<0)
{
printk("Module:Can't get major number.\n");
return result;
}
if(scull_major==0)
scull_major=result;
return 0;
}
void cleanup_module()
{
unregister_chrdev(scull_major,"scull");
printk("Sorry! The testing module is unloading now!");
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("CYC");