Showing posts with label dynamic module. Show all posts
Showing posts with label dynamic module. Show all posts

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