#include <linux/init.h>
#include <linux/module.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/cdev.h>
#include <linux/fcntl.h>
#include <linux/seq_file.h>
#include <asm/system.h>
#include <asm/uaccess.h>
MODULE_LICENSE("GPL");
#define SIZE (4*1024)
static int minor_num = 0;
static int major_num = 0;
struct device
{
char *buf;
struct cdev my_cdev;
};
static struct device *g_my_device;
ssize_t my_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
ssize_t my_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos);
int my_open(struct inode *inode, struct file *filp);
int my_release(struct inode *inode, struct file *filp);
struct file_operations my_fops =
{
.owner = THIS_MODULE,
.read = my_read,
.write = my_write,
.open = my_open,
.release = my_release,
};
static int __init my_device_init(void)
{
dev_t dev_num = 0;
int res;
int err;
res = alloc_chrdev_region(&dev_num, minor_num, 1, "steven_device");
major_num = MAJOR(dev_num);
if (res < 0)
{
printk("STEVEN alloc_chrdev_region error!\n");
return -1;
}
g_my_device = kmalloc(sizeof(struct device), GFP_KERNEL);
if (NULL == g_my_device)
{
printk("STEVEN in %s[%d] kmalloc error!\n", __FUNCTION__, __LINE__);
}
memset(g_my_device, 0, sizeof(struct device));
g_my_device->buf = kmalloc(sizeof(unsigned char) * SIZE, GFP_KERNEL);
memset(g_my_device->buf, 0, sizeof(unsigned char) * SIZE);
cdev_init(&(g_my_device->my_cdev), &my_fops);
g_my_device->my_cdev.owner = THIS_MODULE;
g_my_device->my_cdev.ops = &my_fops;
err = cdev_add(&(g_my_device->my_cdev), dev_num, 1);
if (err != 0)
printk("STEVEN: cdev_add error!\n");
return 0;
}
void __exit my_device_exit(void)
{
dev_t dev_num;
dev_num = MKDEV(major_num, minor_num);
cdev_del(&(g_my_device->my_cdev));
kfree(g_my_device->buf);
kfree(g_my_device);
unregister_chrdev_region(dev_num, 1);
return;
}
ssize_t my_read (struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
int ret;
if ((g_my_device->buf)[0] == '\0')
{
ret = strlen("NULL");
copy_to_user(buf, "NULL", strlen("NULL"));
return 0;
}
if (0 != copy_to_user(buf, g_my_device->buf, count))
{
printk("STEVEN: copy_to_user error!\n");
return 0;
}
else
return count;
}
ssize_t my_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
memset(g_my_device->buf, 0, sizeof(char) * SIZE);
if (0 != copy_from_user(g_my_device->buf, buf, count))
{
printk("STEEVN: copy_from_user error!\n");
return 0;
}
else
return count;
}
int my_open(struct inode *inode, struct file *filp)
{
struct device *my_device;
my_device = container_of(inode->i_cdev, struct device, my_cdev);
filp->private_data = my_device;
return 0;
}
int my_release(struct inode *inode, struct file *filp)
{
return 0;
}
module_init(my_device_init);
module_exit(my_device_exit);
|