
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>

#define BUFFER_SIZE   8192

char data_buffer[BUFFER_SIZE];
int  used_buffer = 0;


/*----------------------------------------------------------*/
/* Treiber - Implementierung                                */
/*----------------------------------------------------------*/

static ssize_t my_read(struct file * file, char * buf,
			 size_t count, loff_t *ppos)
{
    int bytes_to_copy = used_buffer - *ppos;

    if (bytes_to_copy <= 0)
        return 0;

    if (bytes_to_copy > count)
        bytes_to_copy = count;

    copy_to_user(buf, &data_buffer[*ppos], bytes_to_copy);

    *ppos += bytes_to_copy;

	return bytes_to_copy;
}

static ssize_t my_write(struct file * file, const char * buf,
			  size_t count, loff_t *ppos)
{
    int bytes_to_copy;

    if (*ppos >= BUFFER_SIZE)
        return -ENOMEM;

    if (count > BUFFER_SIZE - *ppos)
        bytes_to_copy = BUFFER_SIZE - *ppos;
    else
        bytes_to_copy = count;

    copy_from_user(&data_buffer[*ppos], buf, bytes_to_copy);

    *ppos += bytes_to_copy;
    used_buffer = *ppos;

	return bytes_to_copy;
}

static int my_open(struct inode* inode, struct file* filep)
{
	MOD_INC_USE_COUNT;
    return 0; /* success */
}

static int my_release(struct inode* inode, struct file* filep)
{
	MOD_DEC_USE_COUNT;
    return 0; /* success */
}



struct file_operations my_fops =
{
    read:    my_read,
    write:   my_write,
    open:    my_open,
    release: my_release
};


/*----------------------------------------------------------*/
/* Modul-Initialisierung (Registrierung des Treibers)       */
/*----------------------------------------------------------*/

unsigned int my_major;

int init_module(void)
{
    SET_MODULE_OWNER(&my_fops);

    my_major = register_chrdev(0, "my_chrdev", &my_fops);
    if (my_major < 0)
    {
        printk(KERN_WARNING "my_chrdev: error registering char device\n");
        return my_major;
    }

    return 0;
}

void cleanup_module(void)
{
    unregister_chrdev(my_major, "my_chrdev");
}
