[ create a new paste ] login | about

Link: http://codepad.org/0eVoe3vI    [ raw code | fork ]

geekoutlaw - C, pasted on Oct 15:
/*-------Code for the Character driver------*/
     
 
/* Header files Include*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <asm/uaccess.h> /* copy_from/to_user */
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/list.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/vmalloc.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/wait.h>
#include <linux/sched.h>
//#include <linux/kdev_t.h>

/* Define parameter used in char driver */

#define LTE_MAJOR 100
#define LTE_MINOR 0
#define LTE_DEVNAME "/dev/lte"
#define DEV_COUNT 1
#define	BUFF_LEN 12288
#define DATA_TO_KERNEL 1
#define DATA_TO_USER 2


MODULE_LICENSE("DUAL BSD/GPL");
MODULE_AUTHOR("MILIND");

/* Global Declaration */
dev_t lte_dev;
int device_open =0;
wait_queue_head_t lte_poll_wq;
char         *message_ptr = NULL;
unsigned int write_poll_data =0;


/* Structure defination */

struct cdev *lte_cdev;

/*============================================================================================================*/
/*  Open and Release Function */

static int lte_dev_open(struct inode *inode ,struct file *file)
{
	printk(KERN_INFO"device open (%p,%p)\n", inode, file);

	/* we don't want to talk to two processes at the sametime */
		 
	if(device_open) 
	{
		printk(KERN_INFO"Please Check device is Open");
		return -EBUSY ;
	}
	
	device_open++;
	
	
		return 0;
}
/*============================================ZZZZZZZZZZZZZZZ================================================*/

static int lte_dev_release(struct inode *inode, struct file *file)
{
	printk(KERN_INFO"device release (%p,%p)\n", inode, file);
	
	device_open--;
		return 0;
}



/*============================================ZZZZZZZZZZZZZZZ================================================*/
/* using mmap() function*/
//struct vm_area_struct *vma;
static int lte_dev_mmap(struct file *file, struct vm_area_struct *vma)
{
	printk("Hello Neo\n");
	
#if 1	
	if (remap_pfn_range(vma, vma->vm_start,
			virt_to_phys((void*)((unsigned long)message_ptr)) >> PAGE_SHIFT,
			vma->vm_end - vma->vm_start, PAGE_SHARED)!= 0)
	{
		return -EAGAIN;
	}
#endif

#if 0	
	if (remap_pfn_range(vma, vma->vm_start,
			virt_to_phys((void*)((unsigned long)message_ptr)) >> PAGE_SHIFT,
			BUFF_LEN, PAGE_SHARED)!= 0)
	{
		return -EAGAIN;
	}
#endif
	
	printk("message_ptr %x\n", message_ptr);
	printk("message_ptr physical %x\n", virt_to_phys((void*)((unsigned long)message_ptr)) >> PAGE_SHIFT);
	printk("Hello Neo Success\n");
	return 0;
}
/*============================================ZZZZZZZZZZZZZZZ================================================*/

static long lte_dev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	    int  i;
   unsigned char message[BUFF_LEN];
	#if 0
		for (i=0;i<BUFF_LEN;i++)
		{
			message[i]= i+3;
			printk("%d\t", message[i]);
		}
#endif	


	printk("\ncmd=%d\n",cmd);

	switch(cmd)
	{
		case DATA_TO_KERNEL:
			printk(KERN_INFO"Receving Data from User = %p\n", message_ptr);
			for (i=0;i<BUFF_LEN;i++)
			{
				printk("%d\t", message_ptr[i]);
			}
			printk("\n");
			
		break;

		case DATA_TO_USER:
			
		for (i=0;i<BUFF_LEN;i++)
		{
			message[i]= i+5;
			printk("%d\t", message[i]);
		}
			printk("\n");
			memcpy(message_ptr,message,BUFF_LEN);
			write_poll_data = 1;
			wake_up_poll(&lte_poll_wq, 1);
		//	printk(KERN_INFO"Sending Data to User = %d\n", message[0]);
		break;
		
		default :
		break;
	}
	return 0;
}

static unsigned int lte_dev_poll (struct file *fd, poll_table *wait)
{
	int mask = 0;
	poll_wait(fd, &lte_poll_wq, wait);
	if (write_poll_data) {
		printk(KERN_INFO"\nInvoke User for reading the data\n");
		mask = (POLLIN | POLLRDNORM);
		write_poll_data = 0;  /* This is for taking next data */
	}
	
	return mask;
}

/*============================================ZZZZZZZZZZZZZZZ================================================*/
static const struct file_operations lte_dev_fops= 
		{
			.open 		= lte_dev_open,
			.unlocked_ioctl	= lte_dev_ioctl,
            		.mmap		= lte_dev_mmap,
			.poll		= lte_dev_poll,
			.release	= lte_dev_release
		};


/*============================================ZZZZZZZZZZZZZZZ================================================*/
/* Declaration of init and exit function*/
static int lte_dev_init(void)
{
	int ret_val;
	
	printk(KERN_INFO"LTE DEVICE REGISTERING\n ");

	/* Register the lte_dev*/
	if (LTE_MAJOR)
	{
		lte_dev = MKDEV(LTE_MAJOR, LTE_MINOR);	
		ret_val= register_chrdev_region(lte_dev, DEV_COUNT, LTE_DEVNAME);
		printk("ret_val = %d \n", ret_val);
	}
	else
	{
		ret_val = alloc_chrdev_region(&lte_dev, LTE_MINOR, DEV_COUNT, LTE_DEVNAME);
		printk(KERN_INFO"Hello\n");
		printk(KERN_INFO"ret_val = %d \n", ret_val);  
	}

	if (ret_val < 0) 
	{
		printk(KERN_WARNING "lte: Could not get major number %d\n", LTE_MAJOR);

		return ret_val;
	}

	lte_cdev = cdev_alloc();
        if(lte_cdev != NULL)
	{
		lte_cdev->owner = THIS_MODULE;
		lte_cdev->ops = &lte_dev_fops;
		ret_val = cdev_add(lte_cdev, lte_dev,DEV_COUNT);
	}
	if (ret_val< 0)
	{
		printk(KERN_ALERT"%s failed with %d\n", "Sorry, registering the char_dev",ret_val);
	return 0;
	}

	init_waitqueue_head(&lte_poll_wq);


	message_ptr = (char *)kmalloc(BUFF_LEN  + 2 * PAGE_SIZE, GFP_KERNEL);
	if (!message_ptr) {
		printk("kmalloc failed\n");
		return 0;
	}


printk(KERN_INFO "%s The major device number is %d. \n","Registeration is a success", LTE_MAJOR);
printk(KERN_INFO "If you want to talk to the device driver you'll have to create a device file.\n");
printk(KERN_INFO "We suggest you use: mknod %s c %d 0\n ", LTE_DEVNAME, LTE_MAJOR);
printk(KERN_INFO "The device file name is important, because the ioctl program assumes that's the file you'll use.\n ");
	
	return ret_val;
}


/*============================================ZZZZZZZZZZZZZZZ================================================*/
static void lte_dev_exit(void)
{
	//int ret;
		printk(KERN_INFO"Device succesfully unregistered");
		cdev_del(lte_cdev);
		unregister_chrdev_region(lte_dev, DEV_COUNT);
	//if (ret<0)
	//	printk(KERN_ALERT"Error: unregistered_device: %d\n",ret);
	//return ret;
}



module_exit(lte_dev_exit);
module_init(lte_dev_init);


Create a new paste based on this one


Comments: