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

Sunday, 4 January 2015

I2c Learning

https://www.kernel.org/doc/htmldocs/device-drivers/i2c.html

http://pete.akeo.ie/2011/08/writing-linux-device-driver-for-kernels.html#uds-search-results



Writing I2C Bus driver
-I2c was developed by Philips
-System management Bus(SMBus) is based on this protocol
-I2c has two line bus.One is Serial Data Line(SDL) and other is Serial Clock Line(SCL).
-Pull up resister are requied in SDL and SCL because pin in the chip can only put the line low or other wise the are floating VDD.
-In I2C mechanism, all the devices are considered as node connected to same medium.
-If a node wants to transmit some data, it can determine whether any other node is transmitting data by letting the pull up resistor to make the logical line to1 and monitor the line state.If any nodes pulls the line to 0, then other nodes can detect that some node is transmitting data.
-I2C protocol supports 10 bit addressing but most of the devices supports only 7 bit addressing (slave addresses). So a maximum of 127 devices can connect on a single bus.
Speed
Standard mode : 100 kbps
Fast mode : 400 kbps
 

More about I2C

  1. Every device connected to I2C lines has a unique address.
  2. Master-slave relationship exist between device and the chip.
  3. Master can be either transmitter or receivers.
  4. I2C is a multi-master bus which has collision detection and mechanisms to prevent data corruption when 2 or more master initiates data transfer at same time. 
  5. It is an 8 bit serial bus which bidirectional data transfer is possible.
Many number of devices can be connected to the same bus.                                        We can just try to see how we can configure I2C adapter, bus driver etc.            

Terminology
===========

When we talk about I2C, we use the following terms:
  Bus    -> Algorithm
            Adapter
  Device -> Driver
            Client


-An Algorithm driver contains general code that can be used for a whole class
of I2C adapters. Each specific adapter driver either depends on one algorithm
driver, or includes its own implementation

-A Driver driver (yes, this sounds ridiculous, sorry) contains the general
code to access some type of device. Each detected device gets its own
data in the Client structure. Usually, Driver and Client are more closely
integrated than Algorithm and Adapter.

-A Driver driver (yes, this sounds ridiculous, sorry) contains the general
code to access some type of device. Each detected device gets its own
data in the Client structure. Usually, Driver and Client are more closely
integrated than Algorithm and Adapter.

-At this time, Linux only operates I2C (or SMBus) in master mode; you can't
use these APIs to make a Linux system behave as a slave/device, either to
speak a custom protocol or to emulate some other device.

                                                                                                                    
Writing an I2C Driver
struct i2c_driver {
  unsigned int class;
  int (* attach_adapter) (struct i2c_adapter *);
  int (* probe) (struct i2c_client *, const struct i2c_device_id *);
  int (* remove) (struct i2c_client *);
  void (* shutdown) (struct i2c_client *);                               /* optional */
  int (* suspend) (struct i2c_client *, pm_message_t mesg);             /* optional */
 int (* resume) (struct i2c_client *);                                   /* optional */
  void (* alert) (struct i2c_client *, unsigned int data);
  int (* command) (struct i2c_client *client, unsigned int cmd, void *arg);/* optional deprecated */
  struct device_driver driver;
  const struct i2c_device_id * id_table;
  int (* detect) (struct i2c_client *, struct i2c_board_info *);
  const unsigned short * address_list;
  struct list_head clients;
};
 
struct i2c_client {
  unsigned short flags;
  unsigned short addr;
  char name[I2C_NAME_SIZE];
  struct i2c_adapter * adapter;
  struct device dev;
  int irq;
  struct list_head detected;
  i2c_slave_cb_t slave_cb;
}; 
 
-you will implement a single driver structure, and instantiate all clients from it.  
-a driver structure contains general access routines, and should be zero-initialized except for fields with data you provide.
-A client structure holds device-specific information like the driver model device node, and its I2C address.
-In driver strucure,Name field should match the module name.  If the driver name doesn't match the module name, the module won't be automatically loaded (hotplug/coldplug).


Accessing the client
====================
-To write/read information to client

-I have found it useful to define foo_read and foo_write functions for this.
For some cases, it will be easier to call the i2c functions directly,
but many chips have some kind of register-value idea that can easily
be encapsulated.
 

The below functions are simple examples, and should not be copied
literally. 

 int foo_read_value(struct i2c_client *client, u8 reg)
{
        if (reg < 0x10) /* byte-sized register */
                return i2c_smbus_read_byte_data(client, reg);
        else            /* word-sized register */
                return i2c_smbus_read_word_data(client, reg);
}

int foo_write_value(struct i2c_client *client, u8 reg, u16 value)
{
        if (reg == 0x10)        /* Impossible to write - driver error! */
                return -EINVAL;
        else if (reg < 0x10)    /* byte-sized register */
                return i2c_smbus_write_byte_data(client, reg, value);
        else                    /* word-sized register */
                return i2c_smbus_write_word_data(client, reg, value);
}
 


Device/Driver Binding
---------------------
-System infrastructure , typically  board-specific initialization code or boot firmware, reports what I2C devices exist.  For example, there may be a table, in the kernel or from the boot loader, identifying I2C devices and linking them to board-specific configuration information about IRQs and other wiring artifacts, chip type, and so on.

 That could be used to create i2c_client objects(device file) for each I2C device.

-I2C device drivers using this binding model work just like any other
kind of driver in Linux:  they provide a probe() method to bind to
those devices, and a remove() method to unbind.

        static int foo_probe(struct i2c_client *client,
                             const struct i2c_device_id *id);//for binding
        static int foo_remove(struct i2c_client *client);//for unbinding



-Remember that the i2c_driver does not create those client handles.  The handle may be used during foo_probe().  If foo_probe() reports success (zero not a negative status code) it may save the handle and use it until foo_remove() returns.
 

-The probe function is called when an entry in the id_table name field
matches the device's name. It is passed the entry that was matched so
the driver knows which one in the table matched.


Device Creation
---------------
-If you know for a fact that an I2C device is connected to a given I2C bus, you can instantiate that device by simply filling an i2c_board_info structure with the device address and driver name, and calling i2c_new_device(). This will create device.

-Then the driver core will take care of finding the right driver and will call its probe() method.
-If a driver supports different device types, you can specify the type you want using the type field.  You can also specify an IRQ and platform data if needed.
-Sometimes you know that a device is connected to a given I2C bus, but you don't know the exact address it uses.
-Sometimes you know that a device is connected to a given I2C bus, but you
don't know the exact address it uses.

- In that case, you can use the i2c_new_probed_device() variant, which is
similar to i2c_new_device(), except that it takes an additional list of
possible I2C addresses to probe.

-The call to i2c_new_device() or i2c_new_probed_device() typically happens
in the I2C bus driver.




Device Detection
----------------





Device Deletion
---------------

-Each I2C device which has been created using i2c_new_device() or i2c_new_probed_device() can be unregistered by calling i2c_unregister_device(). 
- If you don't call it explicitly, it will be called automatically before the underlying I2C bus itself is removed, as a device can't survive its parent in the device driver model.

Initializing the driver
=======================
static int __init foo_init(void)
{
        return i2c_add_driver(&foo_driver);
}

static void __exit foo_cleanup(void)
{
        i2c_del_driver(&foo_driver);
}

/* Substitute your own name and email address */
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");

/* a few non-GPL license types are also allowed */
MODULE_LICENSE("GPL");

module_init(foo_init);
module_exit(foo_cleanup);
-Note that some functions are marked by `__init'.  These functions can be removed after kernel booting (or module loading) is completed. Likewise, functions marked by `__exit' are dropped by the compiler when the code is built into the kernel, as they would never be called.



Power Management
================
-activating a system wakeup mechanism -- do that in the suspend() method.
The resume() method should reverse what the suspend() method does.




System Shutdown
===============

If your I2C device needs special handling when the system shuts down
or reboots (including kexec) -- like turning something off -- use a
shutdown() method.

Again, this is a standard driver model call, working just like it
would for any other driver stack:  the calls can sleep, and can use
I2C messaging.

Command function
================

A generic ioctl-like function call back is supported. You will seldom
need this, and its use is deprecated anyway, so newer design should not
use it.


Sending and receiving
=====================

If you want to communicate with your device, there are several functions
to do this. You can find all of them in <linux/i2c.h>.

If you can choose between plain I2C communication and SMBus level
communication, please use the latter. All adapters understand SMBus level
commands, but only some of them understand plain I2C!



Documentation of I2C (user space):(ref dev-interface)

- i2c devices are controlled by a kernel driver. But it is also possible to access all devices on an adapter from userspace, through the /dev interface.
-Each registered i2c adapter gets a number, counting from 0.
-You can examine /sys/class/i2c-dev/ to see what number corresponds to which adapter.
-Alternatively, you can run "i2cdetect -l" to obtain a formated list of all
i2c adapters present on your system at a given time.

-I2C device files are character device files with major device number 89
and a minor device number corresponding to the number assigned as
explained above.


C example
=========
-So let's say you want to access an i2c adapter from a C program

-The first thing to do is "#include <linux/i2c-dev.h>".

-Please note that there are two files named "i2c-dev.h" out there, one is distributed
with the Linux kernel and is meant to be included from kernel driver code, the other one is distributed with i2c-tools and is meant to be included from user-space programs. You obviously want the second one here 


-Next thing, open the device file, as follows:

  int file;
  int adapter_nr = 2; /* probably dynamically determined */
  char filename[20];

  snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
  file = open(filename, O_RDWR);
  if (file < 0) {
    /* ERROR HANDLING; you can check errno to see what went wrong */
    exit(1);
  }

-When you have opened the device, you must specify with what device
address you want to communicate:

  int addr = 0x40; /* The I2C address */

  if (ioctl(file, I2C_SLAVE, addr) < 0) {
    /* ERROR HANDLING; you can check errno to see what went wrong */
    exit(1);
  }

-Well, you are all set up now. You can now use SMBus commands or plain I2C to communicate with your device. SMBus commands are preferred if the device supports them. Both are illustrated below.


 __u8 register = 0x10; /* Device register to access */
  __s32 res;
  char buf[10];

  /* Using SMBus commands */
  res = i2c_smbus_read_word_data(file, register);
  if (res < 0) {
    /* ERROR HANDLING: i2c transaction failed */
  } else {
    /* res contains the read word */
  }

  /* Using I2C Write, equivalent of
     i2c_smbus_write_word_data(file, register, 0x6543) */
  buf[0] = register;
  buf[1] = 0x43;
  buf[2] = 0x65;
  if (write(file, buf, 3) ! =3) {
    /* ERROR HANDLING: i2c transaction failed */
  }

  /* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */
  if (read(file, buf, 1) != 1) {
    /* ERROR HANDLING: i2c transaction failed */
  } else {
    /* buf[0] contains the read byte */
  }
-Note that only a subset of the I2C and SMBus protocols can be achieved by the means of read() and write() calls. In particular, so-called combined transactions (mixing read and write messages in the same transaction) aren't supported. For this reason, this interface is almost never used by user-space programs.


I2C Core-The I2C core is a code base consisting of routines and data structures available to host adapter drivers and client drivers.

Comment to this blog if any query




Monday, 8 September 2014

Character drivers for linux

Character device driver
Today we will go thought character device driver. I am reading linux device driver(LDD) book and noting points in this blog.I will also present simple and miscellaneous codes on to this blog.If you find this theory portion boring you can skip it and move directly to practical side of blog. But I recommend to read the theory portion if you are new to this subject.

-Mainly there are three types of device drivers
1)char:to transfer stream of bytes
2)block:to transfer data in blocks of data.block size can be 512 or more in power of 2
3)network:they are used for network protocol

-Great thing of linux is every thing is file in linux. So character drivers are also files.So you can manipulate this file and control the device. This files are known as device file. They are present in /dev/char
$ls -l /dev/char
    this would give you all device file

- Each device file are represented my major number and minor number
 When a device file is opened, Linux examines its major number and forwards the call to the driver registered for that device.

The Internal Representation of Device Numbers
Within the kernel, the dev_t type (defined in <linux/types.h>) is used to hold device
numbers—both the major and minor parts.
MAJOR(dev_t dev);
MINOR(dev_t dev);

If, instead, you have the major and minor numbers and need to turn them into a dev_t, use:
MKDEV(int major, int minor);
A device file is a special file. It can’t just be created using cat or gedit or shell redirection for that matter.
mknod path type major minor

chmod flag path   //used to give mode

Allocating and Freeing Device Numbers
Now we have to register device
int register_chrdev_region(dev_t first, unsigned int count, char *name);
-first is the device number to the first device,then comes count that is total number of continuous devices,then it gives name to our file.Name would be visible in
 /proc/devices and sysfs.


-You should know your major number and minor number to use this API
-If this API returns 0 then it means device is succefully register


-If you dont know which major number to assign then there is know API which gives major number dynamically.
 int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,unsigned int count, char *name);


-To free memory  use this API
void unregister_chrdev_region(dev_t first, unsigned int count);

-disadvantage for dynamic allocation is that it cant create device node in advance 
-above API only gives number to your driver.It does not connect your driver.So we will learn now how to connect driver

Some Important Data Structures
1)struct file_operations,
2)struct file,
3)struct inode

1)File Operations
Conventionally, a file_operations structure or a pointer to one is called fops

struct module *owner
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*aio_read)(struct kiocb *, char __user *, size_t, loff_t);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_write)(struct kiocb *, const char __user *, size_t, loff_t *);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int);
.
.
.
there many such structures in file operation
this is example how file operation.More clearity will come when you check the code for char driver 
struct file_operations scull_fops = {
.owner =THIS_MODULE,
.llseek =scull_llseek,
.read =scull_read,
.write =scull_write,
.ioctl =scull_ioctl,
.open =scull_open,
.release = scull_release,
};

2)file structure(struct file)
-struct file, defined in <linux/fs.h>

-The file structure represents an open file

field of file structure are
-mode_t f_mode;The file mode identifies the file as either readable or writable (or both), by means of the bits FMODE_READ and FMODE_WRITE
-loff_t f_pos:The current reading or writing position
-unsigned int f_flags-These are the file flags, such as O_RDONLY, O_NONBLOCK, and O_SYNC. O_NONBLOCK is mostly used
-struct file_operations *f_op-The operations associated with the file.
-void *private_data;
-struct dentry *f_dentry;


3)inode structure
The inode structure is used by the kernel internally to represent files.
dev_t i_rdev;
For inodes that represent device files, this field contains the actual device number.
struct cdev *i_cdev;
struct cdev is the kernel’s internal structure that represents char devices; this
field contains a pointer to that structure when the inode refers to a char device
file.
 -this macro are used to get major number and minor number from inode of device file
unsigned int iminor(struct inode *inode);
unsigned int imajor(struct inode *inode);
this should be used instead of using i_rdev

We are done with data structure.Now we move forward for char device registration 
-struct cdev is used to represent char device present in <linux/cdev.h>

-There are two ways of allocating and initializing one of these structures

1)This is at runtime
struct cdev *my_cdev = cdev_alloc( );
my_cdev->ops = &my_fops;


2)void cdev_init(struct cdev *cdev, struct file_operations *fops);
-finally when cdev structure is set up now its time to tell kernel with this API
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
-as soon as cdev_add returns, your device is “live” and its operations
can be called by the kernel.
-To remove a char device from the system, call:
void cdev_del(struct cdev *dev);

-For completeness, we describe the older char device registration interface.Classic way to register device
int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);
name is name of driver that reappears in /proc/devices 
int unregister_chrdev(unsigned int major, const char *name);

cdev_init() - used to initialize struct cdev with the defined file_operations
cdev_add()  - used to add a character device to the system. 
cdev_del()  - used to remove a character device from the system
After a call to cdev_add(), your device is immediately alive. All functions you defined (through the file_operations structure) can be called.




Note:
struct cdev is one of the elements of the inode structure. As you probably may know already, an inode structure is used by the kernel internally to represent files. The struct cdev is the kernel's internal structure that represents char devices. So this field is a pointer to that structure while the inode refers to the char device file. Therefore if the kernel has to invoke the device it has to register a structure of this type.
some commands(let chardev be our device file)
ls -l /dev
mknod /dev/chardev 60 0
echo "jay kothari">/dev/chardev
cat /dev/chardev
modinfo (driver name)
lsmod | grep (driver name)


With this we compete the registration of char device


Practical:
 Now lets try to load a character driver for number of devices:
 step1:
-go to
$sudo cd /usr/src/linux-(version)/drivers/char
$mkdir (folder name)
$cd (folder name)
$vi (file name).c
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//
#include <linux/init.h>       
#include <linux/module.h>
#include <linux/kernel.h>

#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
/*    fs/char_dev.c, drivers/base/class.c
 *    drivers/base/core.c
 */
#include <linux/slab.h>
#include <linux/kfifo.h>

#define MAX_SIZE 4096

int ndevices=5;
module_param(ndevices,int,S_IRUGO);

typedef struct private_object
{
    struct cdev cdev;
    unsigned char* pbuf;
    struct kfifo kf1;
    struct list_head lentry;
}C_DEV;
LIST_HEAD(phead);
dev_t pseudo_dev_id;

struct class *pseudo_cls;


//******************************************open()**************************************************************//
static int pseudo_open(struct inode *inode,struct file *file)
{
     C_DEV* probj=container_of(inode->i_cdev,C_DEV,cdev);
    printk("pseudo open method\n");
    file->private_data=probj;
    return 0;
}
//close(fd);
static int pseudo_release(struct inode *inode,struct file *file)
{
    printk("pseudo close method\n");
    return 0;
}
//****************************************read()******************************************************************//
static ssize_t pseudo_read(struct file *file, char __user *ubuf,size_t count, loff_t *ppos)
{
    unsigned char* tbuf=kmalloc(count+1,GFP_KERNEL);

    C_DEV* pdev=file->private_data;
    int len=kfifo_len(&pdev->kf1);

    int ret,nbytes;
    printk("pseudo read method entered\n");
   
    if(count>len)
        count=len;//min(count,length)//
    if(count==0) return -EAGAIN;
   
    nbytes=kfifo_out(&pdev->kf1,tbuf,count);
    printk("read:nbytes=%d\t,count=%d\t,off=%d\t,kfifo length=%d\n",nbytes,count,*ppos,kfifo_len(&pdev->kf1));
    tbuf[nbytes]=0;
    printk("read:tbuf=%s\n",tbuf);
    ret=copy_to_user(ubuf,tbuf,nbytes);
//    printf("tbub%s\n",*tbuf);
    printk("read::ret=%d\n",ret);
    if(ret) return -EFAULT;
//    *ppos += nbytes;
    kfree(tbuf);
    return nbytes;
}
//*****************************************************************************************************************//
//**********************************write()***********************************************************************//
static ssize_t pseudo_write(struct file *file, const char __user *ubuf,size_t count, loff_t *ppos)
{
    C_DEV* pdev=file->private_data;
   
    int nbytes;
   
    int remain=kfifo_avail(&pdev->kf1);
    unsigned char* tbuf=kmalloc(count,GFP_KERNEL);

    printk("write:pseudo write method entered,remain=%d\n",remain);
    if(remain==0)
        return -EAGAIN;
    if(count > remain)
        count=remain;    //min(count,remain)
   
    if(copy_from_user(tbuf,ubuf,count))
        return -EFAULT;
      nbytes=kfifo_in(&(pdev->kf1),tbuf,count);

   
    printk("nbytes=%d\t,count=%d\t,off=%d\t,kfifo length=%d\t",nbytes,count,*ppos,kfifo_len(&pdev->kf1));
//    *ppos += nbytes;
    kfree(tbuf);
    return nbytes;
}
//*****************************************************************************************************************//
//*************************************file operation**************************************************************//
static struct file_operations pseudo_fops=
{
    .open=pseudo_open,
    .release=pseudo_release,
    .read=pseudo_read,
    .write=pseudo_write,
    .owner=THIS_MODULE,
    //.ioctl.pseudo_ioctl
};
//******************************************************************************************************************//

//*********************************************init function()*****************************************************//
static int pseudo_init(void)   
{
    int ret,i=0;
    C_DEV* pdev;     //struct private_object* pdev;
    ret=alloc_chrdev_region(&pseudo_dev_id,0,ndevices,"pseudo_char_driver");
    if(ret<0)    return -EFAULT;
    printk("driver registered,major=%d\n",
            MAJOR(pseudo_dev_id));
    pseudo_cls=class_create(THIS_MODULE,"pseudo_class");
    //per device initialization
    for(i=0;i<ndevices;i++)
    {
     pdev=kmalloc(sizeof(C_DEV),GFP_KERNEL);
     pdev->pbuf=kmalloc(MAX_SIZE,GFP_KERNEL);
     kfifo_init(&(pdev->kf1),pdev->pbuf,MAX_SIZE);
    // kfifo_alloc(&pdev->kf1,MAX_SIZE,GFP_KERNEL);//*
     cdev_init(&pdev->cdev,&pseudo_fops);
     kobject_set_name(&(pdev->cdev.kobj),"my_pseudo_dev%d",i);
     ret=cdev_add(&pdev->cdev,pseudo_dev_id+i,1);
     if(ret<0)
    {
        printk("cdev_add failed\n");
        kfifo_free(&pdev->kf1);
        //unregister the driver
        return -EFAULT;
    }
    list_add_tail(&pdev->lentry,&phead);
    device_create(pseudo_cls,NULL,pseudo_dev_id+i,NULL,"pchardev%d",i);
    printk("device initialized:%d\n",i);
        }
        printk("Pseudo Char Driver registered successfully\n");
        return 0;
}
//*****************************************************************************************************//
//*****************************************exit*******************************************************//
static void pseudo_exit(void)   
{
    struct list_head *ptemp,*qtemp;
    C_DEV* pdev;
    int i=0;
    //per device cleanup/deallocation
    list_for_each_safe(ptemp,qtemp,&phead)
    {
        pdev=container_of(ptemp,C_DEV,lentry);
        kfifo_free(&pdev->kf1);
        cdev_del(&pdev->cdev);
        kfree(pdev);
        device_destroy(pseudo_cls,pseudo_dev_id+i);
        printk("cleaned device:%d\n",i);
        i++;
    }

    class_destroy(pseudo_cls);
    unregister_chrdev_region(pseudo_dev_id,5);

    printk("Pseudo Char Driver:Bye\n");   
}
//********************************************************************************************************//

module_init(pseudo_init);
module_exit(pseudo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jay Kothari");
MODULE_DESCRIPTION("driver for n number of device");

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//

-step 2:
make a Makefile in this same folder as follwing
$vi Makefile 

obj-m += (file name).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

-step 3:
Now compile using make
$make
 $ls
check .ko file is generated?

-step4
now load the module to the kernel using insmod command
$insmod (file name).ko

-step 5:
now go to user space /home director
then make a folder
$mkdir(folder name)

-step6:
write a c program that all the char device file
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//
#include<stdio.h>
#include<fcntl.h>
#include<assert.h>
#include<string.h>

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

    int fd=open("/dev/pchardev3",O_RDWR);
    if(fd<0)
    {perror("open error");
    exit(3);
    }
    int k;
      k= write(fd,argv[1],strlen(argv[1]));
        if(k<0)
    {perror("write");
        exit(2);
    }
   
         printf("write is done\n");
                k= read(fd,buf,100);
         if(k<0) {
             perror("read");
             exit(1);
         }  
         buf[k]='\0';
         printf("%s\n",buf);

        printf("%s\n",buf);
        return 0;
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//

-step 7:
make compile this in user space and run it
gcc -(file_name).c -o (file_name)
./(file_name) "JAY KOTHARI"


//------------------------------------------------------------------------------------------------------------------//

-There a code for single character driver that i found from net you can check it out as I used it as my reference code to make this code.Haven’t change authors name to give him honor and I am thankful to him.

  • #include <linux/kernel.h>
  • #include <linux/module.h>
  • #include <linux/moduleparam.h>
  • #include <linux/init.h>
  • #include <linux/slab.h>
  • #include <linux/fs.h>
  • #include <linux/fcntl.h>
  • #include <linux/stat.h>
  • #include <linux/types.h>
  • #include <linux/errno.h>
  • #include <asm/system.h>
  • #include <asm/uaccess.h>
  •  
  • #define DEVICE_NAME "chardev"
  • #define BUFFER_SIZE 1024
  •  
  • MODULE_LICENSE("Dual BSD/GPL");
  • MODULE_AUTHOR("Zobayer Hasan");
  • MODULE_DESCRIPTION("A simple character device driver.");
  • MODULE_SUPPORTED_DEVICE(DEVICE_NAME);
  •  
  • int device_init(void);
  • void device_exit(void);
  • static int device_open(struct inode *, struct file *);
  • static int device_release(struct inode *, struct file *);
  • static ssize_t device_read(struct file *, char *, size_t, loff_t *);
  • static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
  •  
  • module_init(device_init);
  • module_exit(device_exit);
  •  
  • static struct file_operations fops = {
  • .read = device_read,
  • .write = device_write,
  • .open = device_open,
  • .release = device_release
  • };
  •  
  • static int device_major = 60;
  • static int device_opend = 0;
  • static char device_buffer[BUFFER_SIZE];
  • static char *buff_rptr;
  • static char *buff_wptr;
  •  
  • module_param(device_major, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
  • MODULE_PARM_DESC(device_major, DEVICE_NAME " major number");
  •  
  • int device_init() {
  • int ret;
  • ret = register_chrdev(device_major, DEVICE_NAME, &fops);
  • if(ret < 0) {
  • printk(KERN_ALERT "chardev: cannot obtain major number %d.\n", device_major);
  • return ret;
  • }
  • memset(device_buffer, 0, BUFFER_SIZE);
  • printk(KERN_INFO "chardev: chrdev loaded.\n");
  • return 0;
  • }
  •  
  • void device_exit() {
  • unregister_chrdev(device_major, DEVICE_NAME);
  • printk(KERN_INFO "chardev: chrdev unloaded.\n");
  • }
  •  
  • static int device_open(struct inode *nd, struct file *fp) {
  • if(device_opend) return -EBUSY;
  • device_opend++;
  • buff_rptr = buff_wptr = device_buffer;
  • try_module_get(THIS_MODULE);
  • return 0;
  • }
  •  
  • static int device_release(struct inode *nd, struct file *fp) {
  • if(device_opend) device_opend--;
  • module_put(THIS_MODULE);
  • return 0;
  • }
  •  
  • static ssize_t device_read(struct file *fp, char *buff, size_t length, loff_t *offset) {
  • int bytes_read = strlen(buff_rptr);
  • if(bytes_read > length) bytes_read = length;
  • copy_to_user(buff, buff_rptr, bytes_read);
  • buff_rptr += bytes_read;
  • return bytes_read;
  • }
  •  
  • static ssize_t device_write(struct file *fp, const char *buff, size_t length, loff_t *offset) {
  • int bytes_written = BUFFER_SIZE - (buff_wptr - device_buffer);
  • if(bytes_written > length) bytes_written = length;
  • copy_from_user(buff_wptr, buff, bytes_written);
  • buff_wptr += bytes_written;
  • return bytes_written;
  • }
  •  
  • /*
  • End of Source Code
  • */


  • And you are done......enjoy......its easy so smile
    what you need to do if you dont understand the code is that you google out each API you find and you would be done

    Still if there are any troubles then let me know
    Thank you

    Bibliography:
    -read chapter 3 of linux device drivers
    -http://zobayer.blogspot.in/2011/07/simple-character-device.html
    -http://www.makelinux.net/ldd3/chp-3-sect-4




    Friday, 5 September 2014

    Hacking USB with opensuse

       I want to hack Linux USB framework and how it works. So I started my work by reading Linux Device Drivers(LDD). Firstly I present some notes from LDD and then we would be playing around with some simple USB Codes that I found on Web.This is how I learn things.I KNOW THIS IS BORING BUT ITS IMPORTANT TO KNOW

    -USB has 4 cables power,ground ,transmit and receive
    -there are 2 types of usb devices host and device.
    -USB drivers live between different kernel subsystem(block,net,char etc) and USB hardware controller.
    -link between USB Driver and USB core is called interface.
    -devices consist of configurations, interfaces, and endpoints and how USB drivers
     bind to USB interfaces, not the entire USB device. 
    -zero or more endpoint makes interface,many interface make configuration.each   interface as its own driver.
     Endpoint:
    -The most basic form of USB communication is though something called an endpoint.
    -Endpoint are uni-direction.They can be in or out.They carry data.
    types of endpoint
    CONTROL
    -Control endpoints are used to allow access to different parts of the USB device.
    -used for  configuring the device, retrieving information about the device, sending commands to the device, or retrieving status reports about the device
    - small in size.
    -every USB device has  “endpoint 0” that is used by the USB core to configure
    the device at insertion time
    INTERRUPT
    -Interrupt endpoints transfer small amounts of data at a fixed rate every time the
    USB host asks the device for data.
    -do not tranfer large data
    - transfers are guaranteed by the USB protocol to always have enough reserved bandwidth to make it through
    BULK
    -Bulk endpoints transfer large amounts of data.
    -If there is not enough room on the bus to send the whole BULK packet, it is split up across multiple transfers to or from the device.
    ISOCHRONOUS
    Isochronous endpoints also transfer large amounts of data, but the data is not
    always guaranteed to make it through.
    -can handle loss of data.

    -Control and bulk endpoints are used for asynchronous data transfers

    -USB endpoints are described in the kernel with the structure struct usb_host_endpoint.
    -struct usb_endpoint_descriptor has real endpoint information
    *** The fields of this structure that drivers care about are:
    bEndpointAddress- address/ IN and OUT
    bmAttributes-type of endpoint.
    wMaxPacketSize- max size that endpoint can handle
    bInterval-that is, the time(milisec) between interrupt requests for the endpoint.

    Interfaces
    -USB endpoints are bundled up into interfaces.
    -USB interface handles only one type of logical connection
    -USB interface are described in  
    1)struct usb_interface structure.this structure core pass to driver and hence driver has control on device
    struct usb_host_interface *altsetting-contains all alternate setting for that selected interface which contain set of end point described in
    2)struct usb_host_endpoint structure.
    -unsigned num_altsetting
    The number of alternate settings pointed to by the altsetting pointer.
    3)struct usb_host_interface *cur_altsetting
    gives current setting
    4)int minor
    gives minor number

    Configurations-USB interfaces are themselves bundled up into configurations.
    -describes configuration with structure struct usb_host_config


    Practical:
    -to check usb device on your linux type following command
    $lsusb
    -for detail description of usb device type
    $lsusb -v


    USB Urbs
    -The USB code in the Linux kernel communicates with all USB devices using some-
    thing called a urb
    -sends data in asynchronous manner
    -urb lifecycle
    1.parents-USB device drivers
    2.assigned-to endpoint
    3.submitted to -core and host controller
    4.processed by-host controller
    5.end-host controller will notify device driver.
    -urbs control api are only used when you are concert with throughput rate(streaming) if you want to transfer only data or control then more simple api are available
    struct urb
    1)struct usb_device *dev
    pointer to device driver to which urb is send
    2)unsigned int pipe
    endpoint information to which urb is send
    3)unsigned int transfer_flags
    4)unsigned int transfer_flags
    usb driver controls urb via this flags
    URB_SHORT_NOT_OK:short read can be considered as error by usb core
    URB_ISO_ASAP
    URB_NO_TRANSFER_DMA_MAP
    URB_NO_SETUP_DMA_MAP
    URB_ASYNC_UNLINK
    URB_NO_FSBR
    URB_ZERO_PACKET
    URB_NO_INTERRUPT
    void *transfer_buffer:in order to properly access buffer it should have memory
    dma_addr_t transfer_dma:buffer to be used to transfer data to USB device using DMA
    int transfer_buffer_length:length of buffer transfer_buffer
    unsigned char *setup_packet:setup packet for control buffer
    usb_complete_t complete
    Pointer to the completion handler function that is called by the USB core when
    the urb is completely transferred or when an error occurs to the urb.
    void *context
    Pointer to a data blob that can be set by the USB driver.
    int actual_length
    When the urb is finished, this variable is set to the actual length of the data
    either sent by the urb (for OUT urbs) or received by the urb (for IN urbs.)
    int status
    When the urb is finished, or being processed by the USB core, this variable is set
    to the current status of the urb.
    int start_frame
    int interval

    int number_of_packets
    int error_count
    struct usb_iso_packet_descriptor iso_frame_desc[0]

    Creating and Destroying Urbs

    struct urb *usb_alloc_urb(int iso_packets, int mem_flags);
    void usb_free_urb(struct urb *urb);

    Interrupt urbs
    void usb_fill_int_urb(struct urb *urb, struct usb_device *dev,
                                       unsigned int pipe, void *transfer_buffer,
                                        int buffer_length, usb_complete_t complete,
                                         void *context, int interval);
     a helper function to properly initialize a urb to be
    sent to a interrupt endpoint of a USB device:

    Bulk urbsvoid usb_fill_bulk_urb(struct urb *urb, struct usb_device *dev,
                                          unsigned int pipe, void *transfer_buffer,
                                           int buffer_length, usb_complete_t complete,
                                            void *context);
    Control urbs
    void usb_fill_control_urb(struct urb *urb, struct usb_device *dev,
                                               unsigned int pipe, unsigned char *setup_packet,
                                               void *transfer_buffer, int buffer_length,
                                                usb_complete_t complete, void *context);
    Isochronous urbs
    they dont have function as above so they must be initialized "by hand"

    Submitting Urbsint usb_submit_urb(struct urb *urb, int mem_flags);


    Completing Urbs: The Completion Callback Handler

     Canceling Urbs
    int usb_kill_urb(struct urb *urb);
    int usb_unlink_urb(struct urb *urb);


    Now this was all about urb in usb.It is used when we need high throughput.Now let us discuss about writing usb device driver


    Writing a USB Driver

     struct usb_device_id
    -__u16 match_flags
     This field is usually never set directly but is initialized by the USB_DEVICE type macros described later.
    -__u16 idVendor
    -__u16 idProduct
    -__u16 bcdDevice_lo
    -__u16 bcdDevice_hi
    -__u8 bInterfaceClass
    -__u8 bInterfaceSubClass
    -__u8 bInterfaceProtocol
    -kernel_ulong_t driver_info

    various macros
    USB_DEVICE(vendor, product)
    USB_DEVICE_VER(vendor, product, lo, hi)
    USB_DEVICE_INFO(class, subclass, protocol)
    USB_INTERFACE_INFO(class, subclass, protocol)







    Registering a USB Driver
    struct usb_driver
    -struct module *owner
    -const char *name
    -const struct usb_device_id *id_table
    -int (*probe) (struct usb_interface *intf, const struct usb_device_id *id)
    -void (*disconnect) (struct usb_interface *intf)




    static struct usb_driver skel_driver = {
    .owner = THIS_MODULE,
    .name = "skeleton",
    .id_table = skel_table,
    .probe = skel_probe,
    .disconnect = skel_disconnect,
    };

    some more callback function
    int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf)
    int (*suspend) (struct usb_interface *intf, u32 state)
    int (*resume) (struct usb_interface *intf)

    Submitting and Controlling a Urb

    usb_control_msg
    int usb_control_msg(struct usb_device *dev, unsigned int pipe,
                                        __u8 request, __u8 requesttype,
                                        __u16 value, __u16 index,
                                        void *data, __u16 size, int timeout);
    usb_bulk_msgint usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
                                     void *data, int len, int *actual_length,
                                      int timeout);


    Now we are almost done.Lets write a simple usb program for pen drive
    Practical:
    1)make a directory(folder) any where in user space
    eg: mkdir myusb
    2)In that directory write following program
     /* myusb.c*/
    //*************************************************************//
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/usb.h>
    static int pen_probe(struct usb_interface *interface, const struct usb_device_id *id)
    {
        printk(KERN_INFO "Pen drive (%04X:%04X) plugged\n", id->idVendor, id->idProduct);
        return 0;
    }
    static void pen_disconnect(struct usb_interface *interface)
    {
        printk(KERN_INFO "Pen drive removed\n");
    }
    static struct usb_device_id pen_table[] =
    {
        { USB_DEVICE(0x058F, 0x6387) },
        {} /* Terminating entry */
    };
    MODULE_DEVICE_TABLE (usb, pen_table);
    static struct usb_driver pen_driver =
    {
        .name = "pen_driver",
        .id_table = pen_table,
        .probe = pen_probe,
        .disconnect = pen_disconnect,
    };
    static int __init pen_init(void)
    {
        return usb_register(&pen_driver);
    }
    static void __exit pen_exit(void)
    {
        usb_deregister(&pen_driver);
    }
    module_init(pen_init);
    module_exit(pen_exit);
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Jay Kothari");
    MODULE_DESCRIPTION("USB Pen Registration Driver");
    //***********************************************************************//
    3)make a Makfile
    obj-m += myusb.o
    all:
        gcc -C /lib/modules/$(shell uname -r)/build M=${PWD} modules
    clean:
        gcc -C /lib/modules/$(shell uname -r)/build M=${PWD} clean

    4)save makefile and type make.This would generate .ko file
    $make

    5)now load this module to kernel with insmod
    $insmod myusb.ko

    6)Congratulation you have made a pen drive usb module

    $lsusb

    7)You can unload module
    $rmmod myusb.ko 

    -We now write a code to get information of usb device
    //*********************************************************************//
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/usb.h>
    static struct usb_device *device;
    static int pen_probe(struct usb_interface *interface, const struct usb_device_id *id)
    {
        struct usb_host_interface *iface_desc;
        struct usb_endpoint_descriptor *endpoint;
        int i;
        iface_desc = interface->cur_altsetting;
        printk(KERN_INFO "Pen i/f %d now probed: (%04X:%04X)\n",
                iface_desc->desc.bInterfaceNumber, id->idVendor, id->idProduct);
        printk(KERN_INFO "ID->bNumEndpoints: %02X\n",
                iface_desc->desc.bNumEndpoints);
        printk(KERN_INFO "ID->bInterfaceClass: %02X\n",
                iface_desc->desc.bInterfaceClass);
        for (i = 0; i < iface_desc->desc.bNumEndpoints; i++)
        {
            endpoint = &iface_desc->endpoint[i].desc;
            printk(KERN_INFO "ED[%d]->bEndpointAddress: 0x%02X\n",
                    i, endpoint->bEndpointAddress);
            printk(KERN_INFO "ED[%d]->bmAttributes: 0x%02X\n",
                    i, endpoint->bmAttributes);
            printk(KERN_INFO "ED[%d]->wMaxPacketSize: 0x%04X (%d)\n",
                    i, endpoint->wMaxPacketSize, endpoint->wMaxPacketSize);
        }
        device = interface_to_usbdev(interface);
        return 0;
    }
    static void pen_disconnect(struct usb_interface *interface)
    {
        printk(KERN_INFO "Pen i/f %d now disconnected\n",
                interface->cur_altsetting->desc.bInterfaceNumber);
    }
    static struct usb_device_id pen_table[] =
    {
        { USB_DEVICE(0x058F, 0x6387) },
        {} /* Terminating entry */
    };
    MODULE_DEVICE_TABLE (usb, pen_table);
    static struct usb_driver pen_driver =
    {
        .name = "pen_driver",
        .probe = pen_probe,
        .disconnect = pen_disconnect,
        .id_table = pen_table,
    };
    static int __init pen_init(void)
    {
        return usb_register(&pen_driver);
    }
    static void __exit pen_exit(void)
    {
        usb_deregister(&pen_driver);
    }
    module_init(pen_init);
    module_exit(pen_exit);
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Jay Kothari");
    MODULE_DESCRIPTION("USB Pen Info Driver");
    //**********************************************************************//
    -do all the steps as above and then load module to kernel
    -we are almost done.I would add more to this blog as I find and learn, till then you try out all this thing.
    -keep smiling .....cya