#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/semaphore.h>
#include <linux/poll.h>
#define GLOBALMEM_SIZE 0X1000
#define MEM_CLEAR 0X1
#define GLOBALMEM_MAJOR 250
static int globalfifo_major = GLOBALMEM_MAJOR;
struct globalfifo_dev {
struct cdev cdev;
unsigned int current_len;
unsigned char mem[GLOBALMEM_SIZE];
struct semaphore sem;
wait_queue_head_t r_wait;
wait_queue_head_t w_wait;
struct fasync_struct *async_queue;
};
struct globalfifo_dev *globalfifo_devp = NULL;
int globalfifo_open(struct inode *inode, struct file *filp)
{
filp->private_data = globalfifo_devp;
return 0;
}
static int globalfifo_fasync(int fd, struct file *filp, int mode)
{
struct globalfifo_dev *dev = filp->private_data;
return fasync_helper(fd, filp, mode, &dev->async_queue);
}
int globalfifo_release(struct inode *inode, struct file *filp)
{
globalfifo_fasync(-1, filp, 0);
return 0;
}
static unsigned int globalfifo_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;
struct globalfifo_dev *dev = filp->private_data;
down(&dev->sem);
poll_wait(filp, &dev->r_wait, wait);
poll_wait(filp, &dev->w_wait, wait);
if(dev->current_len != 0)
mask |= POLLIN | POLLRDNORM;
if(dev->current_len != GLOBALMEM_SIZE)
mask |= POLLOUT | POLLWRNORM;
up(&dev->sem);
return mask;
}
static ssize_t globalfifo_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
/* int ret;
int p = *ppos;
struct globalfifo_dev *dev = filp->private_data;
if(p > GLOBALMEM_SIZE)
return 0;
if(count > GLOBALMEM_SIZE - p)
count = GLOBALMEM_SIZE -p;
if(copy_to_user(buf, (void *)(dev->mem + p), count)){
ret = -EFAULT;
}else{
*ppos += count;
ret = count;
printk(KERN_INFO "read %u bytes form %u\n", count, p);
}
return ret;
*/
int ret = 0;
struct globalfifo_dev *dev = filp->private_data;
DECLARE_WAITQUEUE(wait, current);
down(&dev->sem);
add_wait_queue(&dev->r_wait, &wait);
while(dev->current_len == 0){
if(filp->f_flags & O_NONBLOCK){
ret = -EAGAIN;
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE);
up(&dev->sem);
schedule();
if(signal_pending(current)){
ret = -ERESTARTSYS;
goto out2;
}
down(&dev->sem);
}
if(count > dev->current_len)
count = dev->current_len;
if(copy_to_user(buf, dev->mem, count)){
return -EFAULT;
goto out;
}else{
memcpy(dev->mem, dev->mem + count, dev->current_len - count);
dev->current_len -= count;
printk(KERN_INFO "read %u bytes form %u\n", count, dev->current_len);
}
wake_up_interruptible(&dev->w_wait);
ret = count;
out:
up(&dev->sem);
out2:
remove_wait_queue(&dev->r_wait, &wait);
set_current_state(TASK_RUNNING);
return ret;
}
static ssize_t globalfifo_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
/* unsigned long p = *ppos;
int ret = 0;
struct globalfifo_dev *dev = filp->private_data;
if(p >= GLOBALMEM_SIZE)
return 0;
if(count > GLOBALMEM_SIZE - p)
count = GLOBALMEM_SIZE -p;
if(copy_from_user(dev->mem + p, buf, count))
ret = -EFAULT;
else{
*ppos += count;
ret = count;
}
return ret;
*/
int ret = 0;
struct globalfifo_dev *dev = filp->private_data;
DECLARE_WAITQUEUE(wait, current);
down(&dev->sem);
add_wait_queue(&dev->w_wait,&wait);
while(dev->current_len == GLOBALMEM_SIZE){
if(filp->f_flags & O_NONBLOCK){
ret = - EAGAIN;
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE);
up(&dev->sem);
schedule();
if(signal_pending(current)){
ret = - ERESTARTSYS;
goto out2;
}
down(&dev->sem);
}
if(count > GLOBALMEM_SIZE - dev->current_len)
count = GLOBALMEM_SIZE -dev->current_len;
if(copy_from_user(dev->mem + dev->current_len, buf, count)){
return - EFAULT;
goto out;
}
else{
dev->current_len += count;
printk(KERN_INFO "writen %u bytes from %u\n", count, dev->current_len);
wake_up_interruptible(&dev->r_wait);
if(dev->async_queue)
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
ret = count;
}
out:
up(&dev->sem);
out2:
remove_wait_queue(&dev->w_wait, &wait);
set_current_state(TASK_RUNNING);
return ret;
}
static const struct file_operations globalfifo_fops = {
.owner = THIS_MODULE,
.read = globalfifo_read,
.write = globalfifo_write,
.open = globalfifo_open,
.release = globalfifo_release,
.poll = globalfifo_poll,
.fasync = globalfifo_fasync,
};
static void globalfifo_setup(struct globalfifo_dev *dev, int index)
{
int err, devno = MKDEV(globalfifo_major, index);
cdev_init(&dev->cdev, &globalfifo_fops);
dev->cdev.owner = THIS_MODULE;
err = cdev_add(&dev->cdev, devno, 1);
if(err)
printk(KERN_NOTICE "Error %d adding globalfifo %d", err, index);
}
int globalfifo_init(void)
{
int result;
dev_t devno = MKDEV(globalfifo_major, 0);
if(globalfifo_major)
result = register_chrdev_region(devno, 1, "globalfifo");
else{
result = alloc_chrdev_region(&devno, 0, 1, "globalfifo");
globalfifo_major = devno;
}
if(result < 0)
return result;
globalfifo_devp = kmalloc(sizeof(struct globalfifo_dev), GFP_KERNEL);
if(!globalfifo_devp){
result = -ENOMEM;
goto fail_malloc;
}
memset(globalfifo_devp, 0, sizeof(struct globalfifo_dev));
globalfifo_setup(globalfifo_devp, 0);
sema_init(&globalfifo_devp->sem, 1);
init_waitqueue_head(&globalfifo_devp->r_wait);
init_waitqueue_head(&globalfifo_devp->w_wait);
return 0;
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;
}
void globalfifo_exit(void)
{
cdev_del(&globalfifo_devp->cdev);
kfree(globalfifo_devp);
unregister_chrdev_region(MKDEV(globalfifo_major, 0), 1);
}
module_init(globalfifo_init);
module_exit(globalfifo_exit);
MODULE_AUTHOR("EMPEROR IS TEST");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("I LOVE YOU");
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/semaphore.h>
#include <linux/poll.h>
#define GLOBALMEM_SIZE 0X1000
#define MEM_CLEAR 0X1
#define GLOBALMEM_MAJOR 250
static int globalfifo_major = GLOBALMEM_MAJOR;
struct globalfifo_dev {
struct cdev cdev;
unsigned int current_len;
unsigned char mem[GLOBALMEM_SIZE];
struct semaphore sem;
wait_queue_head_t r_wait;
wait_queue_head_t w_wait;
struct fasync_struct *async_queue;
};
struct globalfifo_dev *globalfifo_devp = NULL;
int globalfifo_open(struct inode *inode, struct file *filp)
{
filp->private_data = globalfifo_devp;
return 0;
}
static int globalfifo_fasync(int fd, struct file *filp, int mode)
{
struct globalfifo_dev *dev = filp->private_data;
return fasync_helper(fd, filp, mode, &dev->async_queue);
}
int globalfifo_release(struct inode *inode, struct file *filp)
{
globalfifo_fasync(-1, filp, 0);
return 0;
}
static unsigned int globalfifo_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;
struct globalfifo_dev *dev = filp->private_data;
down(&dev->sem);
poll_wait(filp, &dev->r_wait, wait);
poll_wait(filp, &dev->w_wait, wait);
if(dev->current_len != 0)
mask |= POLLIN | POLLRDNORM;
if(dev->current_len != GLOBALMEM_SIZE)
mask |= POLLOUT | POLLWRNORM;
up(&dev->sem);
return mask;
}
static ssize_t globalfifo_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
/* int ret;
int p = *ppos;
struct globalfifo_dev *dev = filp->private_data;
if(p > GLOBALMEM_SIZE)
return 0;
if(count > GLOBALMEM_SIZE - p)
count = GLOBALMEM_SIZE -p;
if(copy_to_user(buf, (void *)(dev->mem + p), count)){
ret = -EFAULT;
}else{
*ppos += count;
ret = count;
printk(KERN_INFO "read %u bytes form %u\n", count, p);
}
return ret;
*/
int ret = 0;
struct globalfifo_dev *dev = filp->private_data;
DECLARE_WAITQUEUE(wait, current);
down(&dev->sem);
add_wait_queue(&dev->r_wait, &wait);
while(dev->current_len == 0){
if(filp->f_flags & O_NONBLOCK){
ret = -EAGAIN;
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE);
up(&dev->sem);
schedule();
if(signal_pending(current)){
ret = -ERESTARTSYS;
goto out2;
}
down(&dev->sem);
}
if(count > dev->current_len)
count = dev->current_len;
if(copy_to_user(buf, dev->mem, count)){
return -EFAULT;
goto out;
}else{
memcpy(dev->mem, dev->mem + count, dev->current_len - count);
dev->current_len -= count;
printk(KERN_INFO "read %u bytes form %u\n", count, dev->current_len);
}
wake_up_interruptible(&dev->w_wait);
ret = count;
out:
up(&dev->sem);
out2:
remove_wait_queue(&dev->r_wait, &wait);
set_current_state(TASK_RUNNING);
return ret;
}
static ssize_t globalfifo_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
/* unsigned long p = *ppos;
int ret = 0;
struct globalfifo_dev *dev = filp->private_data;
if(p >= GLOBALMEM_SIZE)
return 0;
if(count > GLOBALMEM_SIZE - p)
count = GLOBALMEM_SIZE -p;
if(copy_from_user(dev->mem + p, buf, count))
ret = -EFAULT;
else{
*ppos += count;
ret = count;
}
return ret;
*/
int ret = 0;
struct globalfifo_dev *dev = filp->private_data;
DECLARE_WAITQUEUE(wait, current);
down(&dev->sem);
add_wait_queue(&dev->w_wait,&wait);
while(dev->current_len == GLOBALMEM_SIZE){
if(filp->f_flags & O_NONBLOCK){
ret = - EAGAIN;
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE);
up(&dev->sem);
schedule();
if(signal_pending(current)){
ret = - ERESTARTSYS;
goto out2;
}
down(&dev->sem);
}
if(count > GLOBALMEM_SIZE - dev->current_len)
count = GLOBALMEM_SIZE -dev->current_len;
if(copy_from_user(dev->mem + dev->current_len, buf, count)){
return - EFAULT;
goto out;
}
else{
dev->current_len += count;
printk(KERN_INFO "writen %u bytes from %u\n", count, dev->current_len);
wake_up_interruptible(&dev->r_wait);
if(dev->async_queue)
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
ret = count;
}
out:
up(&dev->sem);
out2:
remove_wait_queue(&dev->w_wait, &wait);
set_current_state(TASK_RUNNING);
return ret;
}
static const struct file_operations globalfifo_fops = {
.owner = THIS_MODULE,
.read = globalfifo_read,
.write = globalfifo_write,
.open = globalfifo_open,
.release = globalfifo_release,
.poll = globalfifo_poll,
.fasync = globalfifo_fasync,
};
static void globalfifo_setup(struct globalfifo_dev *dev, int index)
{
int err, devno = MKDEV(globalfifo_major, index);
cdev_init(&dev->cdev, &globalfifo_fops);
dev->cdev.owner = THIS_MODULE;
err = cdev_add(&dev->cdev, devno, 1);
if(err)
printk(KERN_NOTICE "Error %d adding globalfifo %d", err, index);
}
int globalfifo_init(void)
{
int result;
dev_t devno = MKDEV(globalfifo_major, 0);
if(globalfifo_major)
result = register_chrdev_region(devno, 1, "globalfifo");
else{
result = alloc_chrdev_region(&devno, 0, 1, "globalfifo");
globalfifo_major = devno;
}
if(result < 0)
return result;
globalfifo_devp = kmalloc(sizeof(struct globalfifo_dev), GFP_KERNEL);
if(!globalfifo_devp){
result = -ENOMEM;
goto fail_malloc;
}
memset(globalfifo_devp, 0, sizeof(struct globalfifo_dev));
globalfifo_setup(globalfifo_devp, 0);
sema_init(&globalfifo_devp->sem, 1);
init_waitqueue_head(&globalfifo_devp->r_wait);
init_waitqueue_head(&globalfifo_devp->w_wait);
return 0;
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;
}
void globalfifo_exit(void)
{
cdev_del(&globalfifo_devp->cdev);
kfree(globalfifo_devp);
unregister_chrdev_region(MKDEV(globalfifo_major, 0), 1);
}
module_init(globalfifo_init);
module_exit(globalfifo_exit);
MODULE_AUTHOR("EMPEROR IS TEST");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("I LOVE YOU");