Thursday 24 February 2011

Parallel Port Driver in linux(Source code)

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>     /* printk() */
#include <linux/slab.h>     /* kmalloc() */
#include <linux/fs.h>         /* everything... */
#include <linux/errno.h>     /* error codes */
#include <linux/types.h>     /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h>     /* O_ACCMODE */
#include <linux/ioport.h>
#include <asm/system.h>     /* cli(), *_flags */
#include <asm/uaccess.h>     /* copy_from/to_user */
#include <asm/io.h>         /* inb, outb */
#include <linux/io.h>                    /* remap_page_range */
#include <asm/irq.h>
#include <linux/irq.h>
#include <linux/signal.h>
#include <linux/version.h>
#include <linux/interrupt.h>           /* spin_lock_bh     */
#include <asm/signal.h>
#include <linux/ioport.h>
#include <linux/delay.h>

#define BASEPORT 0x378
#define MODULE_NAME "My_handler"

MODULE_DESCRIPTION("Dummy Device Driver, V1.0");
MODULE_SUPPORTED_DEVICE("dummy");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("SUMIT GEMINI");


int parlelport_open(struct inode *inode, struct file *filp);
int parlelport_release(struct inode *inode, struct file *filp);
ssize_t parlelport_read(struct file *filp, char *buf,size_t count, loff_t *f_pos);
ssize_t parlelport_write(struct file *filp, const char *buf,size_t count, loff_t *f_pos);
int parlelport_init(void);
void parlelport_exit(void);


struct file_operations parlelport_fops=
{
    owner     :     THIS_MODULE,
    read      :     parlelport_read,
    write     :     parlelport_write,
    open      :     parlelport_open,
    release   :     parlelport_release
};

int parlelport_major = 247;
int port;
int statusport  = BASEPORT + 1;
int controlport = BASEPORT + 2;


irqreturn_t handler(int irq , void *dev_id)
{
        printk (KERN_INFO "\n\nFunction Name : %s \n",__func__);
        return(0);
}


ssize_t parlelport_read(struct file *filp, char *buf,size_t count, loff_t *f_pos)
{
   
    char parlelport_buffer;
    int j;
   
    printk ("\n Function Name : %s\n",__func__);
        printk (" Process Name    : %s\n",current->comm);
        printk (" Process PID     : %d\n",current->pid);
    printk("\n\n");

    parlelport_buffer = 'A';
    printk("<1>parlelport: read value %c from port 0x378\n", parlelport_buffer);

    printk("<1>inb(BASEPORT) is = %x\n",inb(BASEPORT));
    parlelport_buffer = inb(BASEPORT);
    printk("<1>inb(BASEPORT) is = %x\n",inb(BASEPORT));
    printk("<1>parlelport: read value %c from port 0x378\n", parlelport_buffer);

    for (j = 7; j >= 0; j--)
    {
        if ( (parlelport_buffer & (1 << j)) )
            printk("%d", 1);
        else
            printk("%d", 0);
    }
    printk("\n");

     if (copy_to_user(buf, &parlelport_buffer, 1))
        {
                printk (KERN_ALERT "Error : copy_to_user Failed....\n ");
                return -EFAULT;
        }

    if (*f_pos == 0)
    {
        *f_pos+=1;
        return 1;
    }
    else
    {
        return 0;
    }
}

ssize_t parlelport_write( struct file *filp, const char *buf,size_t count, loff_t *f_pos)
{
    char parlelport_buffer;
    unsigned char status, i, maxtries = 10;
    unsigned char nBUSY = 0x80;
   
    printk ("\n Function Name : %s\n",__func__);
        printk (" Process Name    : %s\n",current->comm);
        printk (" Process PID     : %d\n",current->pid);
    printk("\n\n");

    printk("Count is = %d\n", count);
    printk("buf is =   %s\n", buf);

    parlelport_buffer = '5';
    printk("<1>parlelport: write value %c to port 0x378\n", parlelport_buffer);

    if (copy_from_user(&parlelport_buffer,buf,1))
        {
                printk (KERN_ALERT "Error : copy_from_user Failed....\n ");
                return -EFAULT;
        }
   
    printk("<1>parlelport: write value %c to port 0x378\n", parlelport_buffer);

   

    outb(parlelport_buffer,BASEPORT);

     mdelay(3000);
    outb('t',BASEPORT);
    mdelay(3000);
    outb('A',BASEPORT);
    mdelay(3000);
    outb('U',BASEPORT);

    printk("My data is = %c\n",inb(BASEPORT));

    for (i = 0; i < maxtries; i++)
    {
          status = inb(statusport);
        printk("Statusport is = %x\n",status);
           if((status & nBUSY) == 0)
            break;
    }
/*   
    for(i=0;i<5;i++)
    {
        outb(0x00,BASEPORT);
        printk("Statusport is = %x\n",inb(statusport));
        outb(0xf1,BASEPORT);
        printk("Statusport is = %x\n",inb(statusport));
        outb(0x00,BASEPORT);
        printk("Statusport is = %x\n",inb(statusport));
    }   
*/
    return count;
}

int parlelport_open(struct inode *inode, struct file *filp)
{
    printk (KERN_INFO "\n Function Name : %s \n",__func__);
        printk (KERN_INFO " Process Name  : %s\n",current->comm);
        printk (KERN_INFO " Process PID   : %d\n",current->pid);
    printk("\n\n");
    return 0;
}

int parlelport_release(struct inode *inode, struct file *filp)
{
    printk (KERN_INFO "\n Function Name : %s \n",__func__);
        printk (KERN_INFO " Process Name  : %s\n",current->comm);
        printk (KERN_INFO " Process PID   : %d\n",current->pid);
    printk("\n\n");
    return 0;
}

int parlelport_init(void)
{
    int result,ret;

    printk (KERN_INFO "\n Function Name : %s \n",__func__);
        printk (KERN_INFO " Process Name  : %s\n",current->comm);
        printk (KERN_INFO " Process PID   : %d\n",current->pid);
    printk("\n\n");
   
    result = register_chrdev(parlelport_major, "parlelport",&parlelport_fops);
    if (result < 0)
    {
        printk("<1>parlelport: cannot obtain major number %d\n",parlelport_major);
        return result;
    }
   
   
   
    if(request_region(BASEPORT,3,MODULE_NAME))
                printk("\n%s:I/O region busy.",MODULE_NAME);

    ret = request_irq(7, (void *)handler, 0, "parallelport", NULL);
    printk("return code = %d\n", ret);
   
    outb(0x30,BASEPORT);

    printk("<1>Inserting parlelport module\n");
    return 0;
}


void parlelport_exit(void)
{

    printk (KERN_INFO "\n Function Name : %s \n",__func__);
        printk (KERN_INFO " Process Name  : %s\n",current->comm);
        printk (KERN_INFO " Process PID   : %d\n",current->pid);
    printk("\n\n");
   
    unregister_chrdev(parlelport_major, "parlelport");

    release_region(BASEPORT,3);
    free_irq(7,NULL);
    printk("<1>Removing parlelport module\n");
}

module_init(parlelport_init);
module_exit(parlelport_exit);