Showing posts with label device driver. Show all posts
Showing posts with label device driver. Show all posts

Sunday, 18 May 2014

Character device driver using semaphore mechanism in linux

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/capability.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>
#include <linux/sem.h>
#include <linux/vmalloc.h>
#include <linux/ipc.h>
#include <linux/delay.h>
#include <linux/semaphore.h>

int i,shmid;
char a[10]=0;
struct semaphore lock;

static ssize_t sample_char_read(struct file * file, char __user * buf,size_t count, loff_t *ppos)
{
 printk("sample_char2_read size(%ld)\n", count);
 return 0;
}

static ssize_t sample_char_write(struct file *filp, const char *buf,size_t size, loff_t *offp)
{
 ///semaphore locking
 down(&lock);
 printk("sample_char_write size(%ld)\n", size);
 copy_from_user((void *) a,buf,size);
 printk("kernal=%s\n",a);
 msleep(5000);
 //semaphor unlock
 up(&lock);
 return size;
}

int sample_char_open(struct inode *inode, struct file *filp)
{
 printk("sample_char_open\n");
 //semaphore init
 sema_init(&lock, 1);
 return 0;
}

int sample_char_release(struct inode *inode, struct file *filp)
{
 printk("sample_char_release\n");
 return 0;
}

static struct file_operations sample_char_fops = {
 read:sample_char_read,
 write:sample_char_write,
 open:sample_char_open,
 release:sample_char_release,
};

#define sample_major_number 89
#define max_minors 1
static struct cdev char_cdev;
static dev_t dev;

int init_module(void)
{
 int ret = 0;
 dev = MKDEV(sample_major_number, 0);
 printk("\nLoading the sample char device driver\n");
 ret = register_chrdev_region(dev,1, "sample_char");
 if (ret)
 {
  printk("register_chrdev_region Error\n");
  goto error;
 }

 cdev_init(&char_cdev, &sample_char_fops);
 ret = cdev_add(&char_cdev, dev,2);
 if (ret) {
  printk("cdev_add Error\n");
  goto error_region;
 }

 return 0;
 error_region:
 unregister_chrdev_region(dev, max_minors);
 error:
 return ret;
}

void cleanup_module(void)
{
 cdev_del(&char_cdev);
 unregister_chrdev_region(dev, max_minors);
 printk("\nUnloading the sample char device driver\n");
}


TEST FILE


#include<stdio.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

int main(int argc ,char *argv[])
{
 char buf[100] ;
 char i = 0;
 int g;
 memset(buf, 0, 100);
 printf("Input: %s\n", argv[1]);

 int fp = open("/dev/sample_char", O_RDWR);
 if(fp<0)
 {
  perror("not sucess");
 }

 i=fork();

 if(i==0)
 {
  g=write(fp,argv[1], strlen(argv[1]));
 }
 else
 {
  g=write(fp,argv[2], strlen(argv[2]));
  wait(0);
 }
}

MAKE FILE

obj-m += semaphore.o
all:
 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
test:app.c

COMPILATION OF CODE

gcc -o test app.c

character device driver using MUTEX in linux

MUTEX DRIVER

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/capability.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>
#include <linux/vmalloc.h>
#include <linux/ipc.h>
#include <linux/delay.h>
#include <linux/mutex.h>

int i,shmid;
char *a;
struct mutex lock;

static ssize_t sample_char_read(struct file * file, char __user * buf,size_t count, loff_t *ppos)
{
 printk("sample_char2_read size(%ld)\n", count);
 return 0;
}

static ssize_t sample_char_write(struct file *filp, const char *buf,size_t size, loff_t *offp)
{
 //mutex lock
 mutex_lock(&lock);
 printk("sample_char_write size(%ld)\n", size);
 copy_from_user((void *)a,buf,size);
 printk("%s\n",a);
 msleep(3000);
 //mutex unlock
 mutex_unlock(&lock);
 return size;
}

int sample_char_open(struct inode *inode, struct file *filp)
{
 printk("sample_char_open\n");
 //mutex initialization
 mutex_init(&lock);
 a=(void *)vmalloc(20*sizeof(char));
 return 0;
}

int sample_char_release(struct inode *inode, struct file *filp)
{
 printk("sample_char_release\n");
 return 0;
}

static struct file_operations sample_char_fops = {
 read:
 sample_char_read,
 write:
 sample_char_write,
 open:
 sample_char_open,
 release:
 sample_char_release,
};

#define sample_major_number 89
#define max_minors 1

static struct cdev char_cdev;
static dev_t dev;

int init_module(void)
{
 int ret = 0;
 dev = MKDEV(sample_major_number, 0);
 printk("\nLoading the sample char device driver\n");

 ret = register_chrdev_region(dev,1, "sample_char");
 if (ret)
 {
  printk("register_chrdev_region Error\n");
  goto error;
 }

 cdev_init(&char_cdev, &sample_char_fops);
 ret = cdev_add(&char_cdev, dev,2);

 if (ret) {
  printk("cdev_add Error\n");
  goto error_region;
 }

 return 0;
 error_region:
 unregister_chrdev_region(dev, max_minors);
 error:
 return ret;
}

void cleanup_module(void)
{
 cdev_del(&char_cdev);
 unregister_chrdev_region(dev, max_minors);
 printk("\nUnloading the sample char device driver\n");
}


APPLICATION FILE


#include<stdio.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h> // for memset and strlen
#include<sys/types.h>
#include<sys/stat.h>

int main(int argc ,char *argv[])
{
 //
 assert(argc > 1);//abort program if assertion is false
 char buf[100] ;
 char i = 0;
 int g;
 memset(buf, 0, 100);
 printf("Input: %s\n", argv[1]);

 int fp = open("/dev/sample_mutex", O_RDWR);
 if(fp<0)
 {
  perror("not sucess");
 }

 i=fork();
 if(i==0)
 {
  g=write(fp,argv[1], strlen(argv[1]));
 }
 else
 {
  g=write(fp,argv[2], strlen(argv[2]));
  wait(0);
 }
}

Sleeping mechanism in character driver in linux

#include <linux/module.h>
#include <linux/fs.h>  //various structures(fops)
#include <linux/major.h>
#include <linux/capability.h>
#include <asm/uaccess.h> //copy_to/from_user()
#include <linux/cdev.h>  //cdev
#include <linux/wait.h>  //wait queues
#include <linux/sched.h> //Task states (TASK_INTERRUPTIBLE etc)

wait_queue_head_t queue;
int flag = 0;

static ssize_t sample_char_read(struct file * file, char __user * buf,size_t count, loff_t *ppos)
{
  flag = 0;
  wait_event_interruptible(queue, flag == 1);
  printk("sample_char_read size(%ld)\n", count);
 return 0;
}

static ssize_t sample_char_write(struct file *filp, const char *buf,size_t size, loff_t *offp)
{
  flag = 1;
  wake_up_interruptible(&queue);
  printk("sample_char_write size(%ld)\n", size);
        return size;

}

int sample_char_open(struct inode *inode, struct file *filp)
{
       printk("sample_char_open\n");
       return 0;
}

int sample_char_release(struct inode *inode, struct file *filp)
{

       printk("sample_char_release\n");
       return 0;
}

static struct file_operations sample_char_fops =
{
       .read=          sample_char_read,
       .write=          sample_char_write,
       .open=          sample_char_open,
       .release=        sample_char_release,
};

#define sample_major_number 249
#define max_minors 1

static struct cdev char_cdev;
static dev_t dev;

int init_module(void)
{
  int ret = 0;

  dev = MKDEV(sample_major_number, 0);
  printk("\nLoading the sample char device driver\n");

  ret = register_chrdev_region(dev, max_minors, "sample_char");
  if (ret)
   {
     printk("register_chrdev_region Error\n");
   goto error;
   }
  cdev_init(&char_cdev, &sample_char_fops);
  ret = cdev_add(&char_cdev, dev, max_minors);
  if (ret) {
     printk("cdev_add Error\n");
          goto error_region;
  }

  init_waitqueue_head(&queue);
  return 0;

 error_region:
  unregister_chrdev_region(dev, max_minors);
 error:
  return ret;
}

void cleanup_module(void)
{
  cdev_del(&char_cdev);
        unregister_chrdev_region(dev, max_minors);
        printk("\nUnloading the sample char device driver\n");

}

Memory allocation using kmalloc in character driver in linux

#include <linux/module.h>
#include <linux/fs.h>  //various structures(fops)
#include <linux/major.h>
#include <linux/capability.h>
#include <asm/uaccess.h> //copy_to/from_user()
#include <linux/cdev.h>  //cdev
#include <linux/sched.h> //Task states (TASK_INTERRUPTIBLE etc)
#include <linux/slab.h>  //kmalloc/kfree

char *ptr;
#define BUF_SIZE PAGE_SIZE

static ssize_t sample_char_read(struct file * file, char __user * buf,
                       size_t count, loff_t *ppos)
{
 int err;

 printk("sample_char_read size(%ld)\n", count);
 err = copy_to_user((void *) buf, file->private_data, count);
 if (err)
  err = -EFAULT;

 return count;
}

static ssize_t sample_char_write(struct file *file, const char *buf,
                 size_t size, loff_t *offp)
{
 printk("sample_char_write size(%ld)\n", size);

 copy_from_user( (void *)file->private_data , buf, size);
 printk("in private =%s",file->private_data);
 return size;

}

int sample_char_open(struct inode *inode, struct file *filp)
{

 printk("sample_char_open\n");
 filp->private_data = ptr;
 return 0;
}

int sample_char_release(struct inode *inode, struct file *filp)
{
        kfree (ptr);
        printk("sample_char_release\n");
       return 0;
}

static struct file_operations sample_char_fops = {
       read:          sample_char_read,
       write:          sample_char_write,
       open:          sample_char_open,
       release:        sample_char_release,
};

#define sample_major_number 249
#define max_minors 1

static struct cdev char_cdev;
static dev_t dev;

int init_module(void)
{
 int ret = 0;

 dev = MKDEV(sample_major_number, 0);
 printk("\nLoading the sample char device driver\n");

 ret = register_chrdev_region(dev, max_minors, "sample_char");
 if (ret)
 {
  printk("register_chrdev_region Error\n");
  goto error;
 }
 cdev_init(&char_cdev, &sample_char_fops);
 ret = cdev_add(&char_cdev, dev, max_minors);
 if (ret) {
  printk("cdev_add Error\n");
  goto error_region;
 }

 ptr = kmalloc(BUF_SIZE, GFP_KERNEL);
 if (!ptr) {
  pr_info("unable to get memory block\n");
  ret = -ENOMEM;
  goto error_region;
 }
 memset (ptr, 0, BUF_SIZE);

 return 0;

 error_region:
  unregister_chrdev_region(dev, max_minors);
 error:
         return ret;
}

void cleanup_module(void)
{
  cdev_del(&char_cdev);
  unregister_chrdev_region(dev, max_minors);
         printk("\nUnloading the sample char device driver\n");

}

misc character driver using IOCTL call in linux

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/capability.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/ioctl.h>

struct test_ioctl {
        int cmd_no;
        char data[64];
};

#define SAMPLE_IOCTL_MAGIC_NUMBER 's'

#define SAMPLE_IOCTL_CMD_1 \
        _IOR(SAMPLE_IOCTL_MAGIC_NUMBER, 0x1, int)

#define SAMPLE_IOCTL_CMD_2 \
        _IOW(SAMPLE_IOCTL_MAGIC_NUMBER, 0x2, int)

#define SAMPLE_IOCTL_CMD_3 \
        _IO(SAMPLE_IOCTL_MAGIC_NUMBER, 0x3)

#define SAMPLE_IOCTL_CMD_4 \
        _IOWR(SAMPLE_IOCTL_MAGIC_NUMBER, 0x4, struct test_ioctl)

static ssize_t sample_char_read(struct file * file, char __user * buf,
                       size_t count, loff_t *ppos)
{
       printk("sample_char_read size(%ld)\n", count);
       return 0;
}

static ssize_t sample_char_write(struct file *filp, const char *buf,
                 size_t size, loff_t *offp)
{
       printk("sample_char_write size(%ld)\n", size);
       return size;

}

int sample_char_open(struct inode *inode, struct file *filp)
{
       printk("sample_char_open\n");
       return 0;
}

int sample_char_release(struct inode *inode, struct file *filp)
{

       printk("sample_char_release\n");
       return 0;
}

int sample_char_ioctl (struct file *filp,unsigned int cmd, unsigned long arg)
{
 int ret = 0;

 printk("sample_char_ioctl\n");

 switch (cmd) {

 case SAMPLE_IOCTL_CMD_1:
  printk("IOCTL CMD1\n");
  /*Do Something*/
  break;
 case SAMPLE_IOCTL_CMD_2:
  printk("IOCTL CMD2\n");
  /*Do Something*/
  break;
 case SAMPLE_IOCTL_CMD_3:
  printk("IOCTL CMD3\n");
  /*Do Something*/
  break;
 case SAMPLE_IOCTL_CMD_4:
  printk("IOCTL CMD4\n");
  /*Do Something*/
  break;

 default: /*Default option*/
  /*Do Something or return invalid command error*/
  printk("Invalid IOCTL CMD\n");
  ret = -EINVAL;
 }
 return ret;
}

static struct file_operations sample_char_fops = {
       read:          sample_char_read,
       write:          sample_char_write,
       open:          sample_char_open,
       release:        sample_char_release,
 unlocked_ioctl: sample_char_ioctl,
};

static struct miscdevice misc_dev = {
 .minor =  MISC_DYNAMIC_MINOR,
        .name = "sample_misc_dev",
        .fops =  &sample_char_fops,
        .mode = S_IRWXUGO,
};

int init_module(void)
{
 int ret = 0;
 printk("\nLoading the sample misc char device driver\n");
 ret = misc_register(&misc_dev);
 if (ret)
  printk("Unable to register misc dev\n");
 return ret;
}

void cleanup_module(void)
{
        printk("\nUnloading the sample char device driver\n");
 misc_deregister(&misc_dev);

}


TEST FILE


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>

struct test_ioctl {
        int cmd_no;
        char data[64];
};

#define SAMPLE_IOCTL_MAGIC_NUMBER 's'

#define SAMPLE_IOCTL_CMD_1 \
        _IOR(SAMPLE_IOCTL_MAGIC_NUMBER, 0x1, int)

#define SAMPLE_IOCTL_CMD_2 \
        _IOW(SAMPLE_IOCTL_MAGIC_NUMBER, 0x2, int)

#define SAMPLE_IOCTL_CMD_3 \
        _IO(SAMPLE_IOCTL_MAGIC_NUMBER, 0x3)

#define SAMPLE_IOCTL_CMD_4 \
        _IOWR(SAMPLE_IOCTL_MAGIC_NUMBER, 0x4, struct test_ioctl)


int main()
{
 int fd, ret = 0, val = 10;

 fd = open("/dev/sample_misc_dev", O_RDWR);

 printf("file descriptor fd(%d)\n", fd);
 if (fd < 0) {
  printf("File open error\n"); 
  }

  printf("Sending ioctl CMD 3\n");
  ret = ioctl(fd, SAMPLE_IOCTL_CMD_3);
  printf("ioctl ret val (%d) errno (%d)\n", ret, errno);
  perror("IOCTL error: ");

  printf("Sending ioctl CMD 2\n");
  ret = ioctl(fd, SAMPLE_IOCTL_CMD_2, &val);
  printf("ioctl ret val (%d) errno (%d)\n", ret, errno);
  perror("IOCTL error: ");
  close(fd);
}