EmbLogic's Blog

CHARACTER DEVICE DRIVER

CHARACTER DEVICE DRIVER

 

Device driver is a software implemented part of the kernel to provide a interface or interaction between hardware and file system , Device driver runs in kernel space as a part of kernel , which can be load and unload on demand , so these type of device driver are known as dynamically loaded modules.

Driver can be insert in kernel as a module using insmod and can be remove using rmmod these are two basic commands. Though in this article i am going to discuss about char driver that i have implemented.

Implementation :

In my character driver first of all i registered my char driver using

int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);

Unregistered using the follwing function –

void unregister_chrdev_region(dev_t, unsigned);

Till here my driver got least available major number allocated by kernel you can see by doing

cat /proc/devices after inserting the lkm. Now my next task was to add a number devices to my driver and provide them minor number i done this using macro called MKDEV(MAJOR, MINOR). So till here i have allocated major and minor number and registered my char driver with my kernel .

My next task was to create an application in user space and performing read write operation by that application at a specific node that was created by me in file system using node creating command .

mknod node c mjorno minorno

this will create a character driver node in user space our application will be performing read and write operation on this node .

Mapping System calls :

scull_open :

this was the main task to map the read and write operation of application to our driver so when the application gives a system call open() , then our mapped open starts and return a file descriptor to the application .

int scull_open(struct inode *inodep, struct file *filep) ;

 

scull_read :

After opening the device we need to perform read peration on that device so we need to map

our read and write also by using this callback function.

ssize_t scull_read(struct file *filep, char __user *ubuff, size_t size, loff _t *loff) ;

 

scull_write :

After opening the device we need to perform write operation on that device so we need to map

our read and write also by using this callback function.

ssize_t scull_write(struct file *filep, char __user *ubuff, size_t size, loff _t *loff) ;

 

scull_release :

When the application give the call to close the file descriptor then our mapped callback function starts.

int scull_release(struct inode *inodep, struct file *filep) ;

 

Other operations :

I implemented some more operations like ioctl operation used for debugging perpose :

long scull_ioctl(struct file *, unsigned int, unsigned long) ;

And lseek opeartion were also implemented

loff_t scull_llseek(struct file *, loff_t, int);

Device for operations :

Since we were not having any device so for that I have created a memory area on RAM that

was tread as a device memory , I named it SCULL .

Thank YOU

Posted in Character Driver, Device Drivers | Leave a comment

Introduction to Threads

Introduction To THREADS

Threads, like processes are a mechanism to allow a program to do more than one thing at a time. In Linux when a process is created, it already contains a thread, used to execute the main() function. Threads are implemented as lightweight process. A process can have multiple threads of execution and they all share the same process address space and system state information. When a thread is created in a process, the new thread of execution gets its own stack but shares global variables, file descriptors, signal states. When a program creates another thread, nothing is copied. The creating and the created thread share the same memory space, file descriptors, and other system resources as the original. If one thread changes the value of a variable, for instance, the other thread will see the modified value. Similarly, if one thread closes a file descriptor, other threads may not read from or write to that file descriptor. Because a process and all its threads can be executing only one program at a time, if any thread inside a process calls one of the exec functions, all the other threads are ended.

Linux implements the POSIX thread api. All thread functions and data types are declared in the header file <pthread.h>. to use these library calls link the program with the threads library using -lpthread, as they are not included in standard C library.

Thread Creation:

Each process is identified by a thread id of type pthread_t. Upon creation each thread executes a thread function. When this function returns, thread ends. Function to create a thread is

pthread_create(pthread_t* thread, pthread_attr_t * attr, void *(*routine), (void *), void *arg);

thread is a pointer to a pthread_t structure that will be initialized by the function. Later, this structure can be used to reference the thread.

Attr is a pointer to an optional structure pthread_attr_t. This structure can be manipulated using pthread_attr_*() functions. It can be used to set various attributes of the threads (detach policy, scheduling policy, etc.)

start_routine is the function that will be executed by the thread

arg is the private data passed as argument to the start_routine function

Thread Exit :

A thread can exit by calling pthread_exit .This function may be called from within the thread function or from some other function called directly or indirectly by the thread function. The argument to pthread_exit is the thread’s return value. Syntax of pthread_exit is

void pthread_exit(void *retval).

Thread Joining :

When the main() function exits, all threads of the application are destroyed. The pthread_join() function call can be used to suspend the execution of a thread until another thread terminates. This function must be called in order to release the resources used by the thread, otherwise it remains as zombie. Syntax of pthread_join is

int pthread_join(pthread_t thread, void **thread_return);

where thread the thread for which to wait, that was filled by the pthread_create function call. Second argument point to the return value of the thread.

Advantages of using threads:

  • Improves program performance.

  • Reduce system overheads.

  • Enables the better utilization of hardware in multi-core cpu’s.

  • Less demanding on resources as compared to multiple processes.

Disadvantages :

  • Program complexity and requires very careful design.

  • Debugging a multi-threaded application is a difficult task.

  • Deadlocks.

Posted in Project 04: FTP based Client Server using Threads and Sockets | Leave a comment

An article on character device driver

Device drivers are the one of the basic building block s of operating system. Device driver make the particular piece of hardware to respond to a well-defined internal programming interface. There are three types of device driver

Character Driver
Block Driver
Pipe Driver

In character driver byte by byte transfer of data takes place from user space to kernel space and vice – verse. The only relevant difference between a char device and a regular file is that you can always move back and forth in the regular file, whereas most char devices are just data channels, which you can only access sequentially.

Initialization of Character driver

Initialization of driver module is the first step in any driver programming so in the character driver programming . Each piece of code that can be added to the kernel at run time is called a module. The module is linked dynamically to the running kernel using the insmod command. The rmmod command is used to remove the module entry .

module_init(function_name);
module_exit(function_name);

The module_init() and module_exit() macro defined in <Linux/module.h> are used for initialization of initialization function in kernel using insmod and the removal of the initialization function using rmmod.

Registration and unregistration of Driver

The registration of module is done using different function defined in <Linux/fs.h> . The various functions used for registration of the driver are

register_chrdev(unsigned int major,const char *name, const struct file_operation *fops);
extern int alloc_chrdev_region(dev_t * , unsigned minor_no , unsigned nod, driver name);
extern int register_chrdev_region(dev_t, unsigned, const char *);

(*I have used alloc_chrdev_region for registration)

At the time of removal the unregistration of device is done in clean_up function or exit_function the
function for unregistration of driver are

extern void __unregister_chrdev(unsigned int major, unsigned int baseminor,
unsigned int count, const char *name);
extern void unregister_chrdev_region(dev_t, unsigned);

when registration is done kernel give the minor and major no. called inode no. .Major number are used to represent the driver and minor number represent the number of devices administrate by that particular driver. Kernel identify the driver with their major number . In earlier kernel version total 16 bit are used for major no. and minor no., 8 bit for major no. and 8 bit for minor therefore 255 major no. can be allocated by kernel but in new kernel version 32 bits are used from which 12 bits are used for major no. and rest 20 bits are used for minor no. but we still can use only 255 major no. the reason behind it is the 255 major no are defined in the macro in the header file,dev_t type is used to hold device number both major and minor parts. To obtain the major or minor number of dev_t use :

MAJOR(dev_t dev);
MINOR(dev_t dev);

We use scull as a device memory,just like malloc to get memory in user space Kmalloc is used to get memory in kernel space . The garbage in allocated memory in kernel space is remove by :

memset(void *s ,int c ,size_t n);

The first argument refer to the memory location which is to be replaced by the value in second argument and the third argument indicate how of allocated memory should be cleared.Then the deivce is initalized using :

cdev_init(struct cdev *,struct fileoperations * );

cdev_add(struct cdev *,dev_t , nod);

Open and release:-

The open and release operation is performed by the scull_open and scull_release . Open call prepare the device for the future .We know that every thing is in file format, to set a communication between two file the open function is used it make node for every 32 bit inode number so that particular inode number file can use that node for communication .

Scull_open();
Scull_release();
READ and WRITE operation:-
Once the node is open the read and write operation is performed using scull_write and scull_read.
scull_write is to write on kernel space and scull_read to read data of kernel space for these operation
the call copy_from_user and copy_to_user is used. The mapping of all these function are done through
struct file_operation structure.
scull_write(struct file *,const char __user *,ssize_t,loff_t *);
copy_from_user();
scull_read(struct file *,char __user *,ssize_t,loff_t *);
copy_to_user();
that how the data is read and write from and to kernel memory .

 

Posted in Uncategorized | Leave a comment

An Article On Character Driver

The major issue faced by the kernel today is that it has become blotted. So the concept of modularity has been introduced into the kernel programming so that a required module could be loaded into it dynamically.The driver I used to access a device is a character driver which has the property to access a device, character by character. A infinite stream of byte, they provide an unstructured access to the hardware. This device driver is loaded into a kernel space dynamically by using insmod command .After this a dynamic loader comes into play which links the unresolved symbol in the module to the symbol table in the kernel.

INITIALISATION: When a new module is introduced in a kernel it does not know by itself that for what this module is for. Thereby it run it’s initializing function which is called by module_init().That allow the module to register itself to the each and every facility that the module support. In case of device driver it has to allocate , initialize and register a structure for a category of a device that it has to use, specific to character driver this is done by initializing a cdev structure and implementing a file_operations.

EXIT: The delete_module system call calls a function name module_exit() before removing the kernel from a module. The kernel ensure that the device module is not used by any other and the allow it to get removed.

 

As each and every device in the kernel is identified by a unique number which of type dev_t and it’s an 32 bit value which enclose the (major,minor) number in itself. So,the very first task for our is to ask for a dev number from a kernel so that it could recognise our device when it is in action.

MAJOR=Specific to driver,

MINOR=Specific to device,

This is fetch while registration than the second important task is to initialise our device and at this instant we can say that our device has become alive and the next is to add it to character device database.

This is done by cdev_add. cdev_add basically adds the device to the system. What it means essentially is that after the cdev_add operation your new device will get visibility through the /sys/ file system. The function does all the necessary house keeping activities related to that particularly the kobj reference to your device will get inserted at its position in the object hierarchy.

If we have an device with you we can develop driver accordingly and as far as testing is concerned we initiated it by defining a structure named Scull_dev. That have supposed to used a memory on RAM as virtualization of device.

The next objective is to define a device file specific operations that can be manipulated in struct file_operations:

open: To open the device,

close: To close the device,

read: To do an input operations,

write: To do write operations,

and many more as required.

As the device is open using a character driver node which can be consider as an entry point of the device by using mknod -c major minor. Now the device is accessible from the user space. And it’s different system call is mapped to our device routine for the specific device.

Posted in Uncategorized | Leave a comment

CHARACTER DRIVER

Kernel use the Driver to interact with hardware in an efficient manner. Driver is used as a module to support kernel functioning. Hence driver use kernel space. Each driver have an identical Major number range from 0-255 (8 bit number). However actual bits for major number is 12 bits. Each device attached to a driver have its own minor number. This major & minor number constitute to a dev_t type variable which is unique for every device.

Since Driver are modules ,so they can be dynamically inserted & removed from the kernel ,such driver are known as Loadable Kernel module. Character driver is used to transform data from user process . Character driver is able to transform 1 byte(character) thats why it’s called Character Driver.
Each device is reprensented by a struct sculldev which has following members-
struct scullqset sqset(used for making linked list )
struct cdev (used for storing cdev structure)
int quantum (number of bytes to be stored in each quantum)
int qset (number of qset/linked list)
int size (size of the device)

struct scullqset have two member -
struct scullqset *next (for linking next scullqset)
void ** data (for storing data)

For Module programming necessary header files needed to include are <linux/kernel.h> & <linux/module.h> .Module is initialized by ‘module_init’ macro which specifies the function for the initialization .Similarly ‘module_exit’ macro specifies the exit of module. When a module is inserted using insmod <module name> ,function pointed by module_init() is executed & rmmod <module name> executes the function pointed by module_exit(). Every operation performed in initialization function must be reversed in exit function.

For driver registration we may use one of the following functions:
register_chrdev(unsigned int ,const char* ,const struct file_operations *)
register_chrdev_region (dev_t ,unsigned ,const char * )
alloc_chardev_region (dev_t * ,unsigned ,unsigned ,const char *)

In earlier version of linux module were inserted only by register_chrdev .In such case a driver is mapped with a file operations ,also minor no were not set by the developers. However register_chrdev_region & alloc_chrdev_region were further used for driver registration. alloc_chrdev_region not only provide developer to assign starting minor no (2nd argument ) but also ,number of devices can be register with it (3rd argument). First argument stores the address of dev_t variable assigned by the function. Kernel search for the maximum major no which is free & then assign for the major number. Successful registration of driver returns 0 .

A user defined struct sculldev is used to represent the device memory & its metadata . In structure sculldev we have different members like int quantum,int size,int qset,int devsize ,struct cdev * & struct scullqset * . Structure scullqset is used as a linked list for memory allocation & then data storage for the device .So we allocate memory for this structure in kernel space ,using kmalloc . Memory allocated for structure depend on the size of structure & also the number of devices. For kmalloc <linux/slab.h> must be included. As stated earlier , every operation in initialization must be reversed, hence we free the kernel space allocated for sculldev structure in cleanup function.

cdev_init is used to initialize device & map it with the particular file operations routine . All the attributes for structure sculldev are set before cdev_add. cdev-add mapped the dev_t number (provided by alloc_chrdev_region) to the struct cdev type variable ,which is a member of structure sculldev . Each devices are removed using cdev_del function in cleanup function . For these function <linux/cdev.h> must be included.
When a device is initialized we provide some routine operations mapped to struct file_operations f_ops . For eg., when application uses to open device using open call ,then driver execute the file operation routine mapped for the open .application open the device using a node made by mknod node c <major no> <minor no> & they obtain a file descriptor for this particular node.
While driver interacts with api using struct inode * & struct file * . For each individual node there is unique inode * . For each api opening the node gets its individual file *.When Appplication opens a node it goes to an open routine,defined in module. In open routine struct sculldev pointer for particular devices is saved in the filep->private_data for further operations . This is implemented by container_of . In open routine f_flags in struct file & Accessmode are checked,to see in which mode file is opened.
Release routine is mapped to a function in module which is called when the application uses the close() call.
When a application calls write () function, it calls a write routine of module( in struct file_operations). write routine is given as,
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
where first argument is file pointer ,second one is buffer to be write (given by the application in user space),third argument is number of bytes to be write & last argument tells the current position of struct file ,i.e.,filep->f_pos. first of all strcut sculldev pointer is retrieved from filep->private_data , which was saved earlier in the open routine. After this struct scullqset is given memory using kmalloc.(first scullqset which is given the memory is mapped to the struct sculldev). Then the memory is allocated to void **data & void *data[x]. (void **) data & (void *)data[x] take the memory using kmalloc(sizeof(void *) * qset) & kmalloc(sizeof(void *) * qunatum). Hence data[0...7] will be in sequence. Therefoe they can be accessed later. data[x] (quantum) stores number of bytes given in int quantum of struct sculldev. after qset*quantum bytes next scullqset is needed . Hence we use struct scullqset *next for the next scullqset & the adderss of next scullqset is stored in the scullqset *next (member of the struct scullqset *sqset). Simillarly a linked list is formed with the base address of the list is stored in struct scullqset *sqset (member of struct sculldev). For user space buffer to store in kernel memory ,copy_from_user is used which is declared in <linux/uaccess.h> .
Simillarly when read() is called by application ,module runs read routine,
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
struct sculldev associated with the device is retieved by filep->private_data (as in write routine). as base address of struct scullqset is stored in member of strcut sculldev ,data can be retieved in the same way data was weittrn. copy_to_user is used to copy data from kernel space to user space.

Posted in Uncategorized | Leave a comment

Socket Programming

Socket Programming

Socket:

Sockets are basically used for inter process communication within single or over the network systems. So sockets are basically two endpoints of the communication via which we can communicate. So socket represents a single connection between exactly two pieces of software but we can also communicate between multiple piece of softwares but this requires multiple sockets.

*Sockets are use of unidirectional as well as bidirectional communication.

 

Now as we know if we have to work on the network then we have to deal with IP addresses also because each and every system on the network is recognized by its IP address.In this we have one server and many clients to take the service of the server. Notice that the client needs to know the existence of and the address of the server, but the server does not need to know the address of (or even the existence of) the client prior to the connection being established. Notice also that once a connection is established, both sides can send and receive information.

 

Socket Types:

 

There are two widely used socket types, stream sockets, and datagram sockets. Stream sockets treat communications as a continuous stream of characters, while datagram sockets have to read entire messages at once. Each uses its own communications protocol. Stream sockets use TCP (Transmission Control Protocol), which is a reliable, stream oriented protocol, and datagram sockets use UDP (Unix Datagram Protocol), which is unreliable and message oriented.

 

The address of a socket in the Internet domain consists of the Internet address of the host machine (a unique 32 bit address, often referred to as its IP address). In addition, each socket needs a port number on that host. Port numbers are 16 bit unsigned integers. The lower numbers are reserved in Unix for standard services. For example, the port number for the FTP server is 21. It is important that standard services be at the same port on all computers so that clients will know their addresses. However, port numbers above 2000 are generally available.

 

API to establish socket:

 

In server side:

Socket system calls are declaired in the linux system at standard path in the <sys/socket.h> header file.

Firstly we have to make socket with socket() call. When a socket is created, the program has to specify the address domain and the socket type. Two processes can communicate with each other only if their sockets are of the same type and in the same domain. There are two widely used address domains, the unix domain, in which two processes which share a common file system communicate, and the Internet domain, in which two processes running on any two hosts on the Internet communicate. Each of these has its own address format.

 

Bind the socket to an address using the bind() system call. For a server socket on the Internet, an address consists of a port number on the host machine.

 

Listen for connections with the listen() system call

 

Accept a connection with the accept() system call. This call typically blocks until a client connects with the server.

 

In client side:

In the client side also we have to make socket,Connect the socket to the address of the server using the connect() system call

Send and receive data. There are a number of ways to do this, but the simplest is to use the read() and write() system calls.

 

We can check our client and server program by loopback means by giving the IP address “127.0.0.1”.

on client and server side on single system.

 

Thanks

Avtar Singh

Posted in Uncategorized | Leave a comment

Article on POSIX THREADS

Thread Progrmming
Thread:Multiple strands of execution in a single program are called threads. A more precise definition is that athread is a sequence of control within a process.All processes have at least one thread of execution.When a process executes a fork call, a new copy of the process is created with its own variables and its own PID. This new process is scheduled independently, and (in general)executes almost independently of the process that created it. When we create a new thread in aprocess, in contrast, the new thread of execution gets its own stack (and hence local variables) butshares global variables, file descriptors, signal handlers, and its current directory state with the process that created it.

Advantages of Threads:

1.The overhead cost of creating a new thread is significantly less than that of creating a newprocess (though Linux is particularly efficient at creating new processes compared with many other operating systems).

2.Switching between threads requires the operating system to do much less work thanswitching between processes.
3.Multiple threads are much less demanding on resourcesthan multiple processes, and it is more practical to run programs that logically require many
threads of execution on single-processor systems.

Drawbacks of Threads:
1.Debugging a multithreaded program is much, much harder than debugging a single-threadedone, because the interactions between the threads are very hard to control.

2.A program that splits a large calculation into two and runs the two parts as different threadswill not necessarily run more quickly on a single processor machine, unless the calculation truly allows multiple parts to be calculated simultaneously and the machine it is executing on has
multiple processor cores to support true multiprocessing.

How to create Thread:

Threads are created by using system call phtread_create.The first argument of pthread_create is a poniter to thread object,second argument is the attributes of threads,third argument is thread_function and last argument is used to provide argument to the thread_function.

How to join Thread:

Threads are join by using system call phtread_join.The first parameter is the thread for which to wait, the identifier that pthread_create filled in foryou. The second argument is a pointer to a pointer that itself points to the return value from the thread. Like pthread_create, this function returns zero for success and an error code on failure.

how to exit Thread:When a thread terminates, it calls the pthread_exit function, much as a process calls exit when it ter-minates. This function terminates the calling thread, returning a pointer to an object. Never use it to returna pointer to a local variable, because the variable will cease to exist when the thread does so, causing aserious bug.

Posted in Project 04: FTP based Client Server using Threads and Sockets | Leave a comment

Article on Inter Process Communication Part 1

Project Name: Inter Process Communication

Scope: To setup the communication link between two or more processes so as to transfer data to and fro in between the processes.

Description: We have many IPC techniques in Linux like PIPE, FIFO, Shared Memory, Message Queue. We will start this article from our first topic i.e. PIPE.

PIPE is a stream or we can say a path from where we transfer the data from one process to another. For creating a pipe we us system call “PIPE()”. This call will create a stream between two processes and will return two file descriptors. The two file descriptors returned are connected in a special way. Any data written to file_descriptor[1] can be read back from file_descriptor[0]. The data is processed in a first in, first out basis, usually abbreviated to FIFO. This means that if you write the bytes 1, 2, 3 to file_descriptor[1], reading from file_descriptor[0] will produce 1, 2, 3. This is different from a stack, which operates on a last in, first out basis, usually abbreviated to LIFO. As this stream is unnamed, hence it is visible to only those processes in which one process act as parent and another process act as a child. Now the question arises – What is a child process & Parent process.

We have a system call as “fork()”, this call will create process from main process. The created process is called as child and the main process will be named as parent. After creation of child process, we will send the file descriptors to that child process by calling a call “exec()”. This “exec()” call will create a new process and will replace it with the process from which this was called. Child process generated by the fork() call uses same process context but PCB is different. This replace process created by exec() call will have everything different i.e PCB & process context are different. Now this new process and the parent process both are having the file descriptors and with the help of these descriptors these two processes will share data with each other. Important topics here we have are “Orphan Process” & “Zombies”.

Orphan Process - After a call to fork(), generally its the child process that get time slice to execute. Now say of parent process terminates for some reason before child process, we will have a orphan process as it parent process have died. As every child process have some parent this must be made child of some process, in this condition Dispatcher i.e. Process with PID 1 is automatically made its parent.

Zombies – If for some reason a process is dead but haven’t been removed from the process table it is called as Zombie process. Now this can happen in situation when a child process has terminated and parent process gas gone in some kind of infinite loop which don’t allow child process to exit.

 In the next article we will briefly discuss about other IPC techniques – FIFO, Shared memory and Message queue.

Posted in Uncategorized | Leave a comment

Article on Signals:

SIGNALS:
Signals were introduced by the first Unix systems to simplify interprocess communication.The kernel also uses them to notify processes of system events. In contrast to interrupts and exceptions, most signals are visible to User Mode processes. Also signals can be used as a mean of communication between two processes while interrupts can be used as a mean of communication between hardware and kernel(process). Signals serve two main purposes:

  1. To make a process aware that a specific event has occurred.
  2. To force a process to execute a signal handler function included in its code.

A number of system calls allow programmers to send signals and determine how their processes exploit the signals they receive.An important characteristic of signals is that they may be sent at any time to processes whose state is usually unpredictable. Signals sent to a non-running process must be saved by the kernel until that process resumes execution. Blocking signals (described later) require signals to be queued, which exacerbates the problem of signals being raised before they can be delivered.Therefore, the kernel distinguishes two different phases related to signal transmission:

  1. Signal sending:The kernel updates the descriptor of the destination process to represent that a new signal has been sent.
  2. Signal receiving: The kernel forces the destination process to react to the signal by changing its execution state or by starting the execution of a specified signal handler or both.

Each signal sent can be received no more than once. Signals are consumable resources: once they have been received, all process descriptor information that refers to their previous existence is cancelled.Signals that have been sent but not yet received are called pending signals . At any time, only one pending signal of a given type may exist for a process; additional pending signals of the same type to the same process are not queued but simply discarded. In general, a signal may remain pending for an unpredictable amount of time. Some important points about the signals are :

  • When a process executes a signal-handler function, it usually “masks” the corresponding signal, that is, it automatically blocks the signal until the handler terminates.
  • A signal handler therefore cannot be interrupted by another occurrence of the handled signal, and therefore the function doesn’t need to be re-entrant.
  • A masked signal is always blocked, but the converse does not hold.
  • The kernel must remember which signals are blocked by each process. When switching from Kernel Mode to User Mode, check whether a signal for any process has arrived.

The SIGKILL and SIGSTOP signals cannot be explicitly ignored or caught, and thus their default actions must always be executed. Therefore, SIGKILL and SIGSTOP allow a user with appropriate privileges to destroy and to stop, respectively, any process regardless of the defences taken by the program it is executing.

Posted in Project 03: Client Server Communication using Linux and IPC | Leave a comment

Article:Character Driver

About 4 months I have worked upon something called Device Driver (Character Driver, to be specific).Before start working, First of all I needed to know what really a device driver is? As we all know it is the kernel what is directly going to interact with the Hardware and if our application need to access the hardware we need a driver(Specific one for a class of devices)for that in kernel space. As the name suggest a Device Driver is a LKM(Loadable Kernel Module) which drives(runs) our device. The good thing about a Moduler kernel is a Module can be inserted and removed from the runing kernel(using kernel utilities insmod and rmmod respectively)There are three types of devices i.e Character devices like printers, Block devices like Mass storage devices and Network devices like USb modem etc. Now a Character driver is a driver developed to handel character devices.
Now lets explain the basic arch. of a character driver. Memory of our system is devided in to two parts User space and kernel space. Our applications runs in the user space and our driver runs in kernel space. An application cant see anything in kernel space.Driver is just like a black box for the application developer. So if the application need to access the kernel space, it need a fifo in the VFS(Virtual File System) layer. We create this for the specific device using mknod. In kernel space a driver is identified by its unique 12bit major number and a device is identified by its uniqe 20bit minor number. This 32bit unique number is called dev id(device id). This 32bit no is obtained for a device using a kernel MACRO i.e alloc_chrdev_region(). This registration is to be done right after inserting our module in to the kernel and it should also be unregistered befor removing the module.
There are four most important structures, knowing about those was very much needed. First one is struct cdev. This structure is the representation of a character device in the kernel. This one have a lot of hardware specific information of the device. its most important members are dev(for dev id),owner(owner of the device, the module itself) and *fops (pointer to the struct file_operations). Second one in struct file_operations which is a collection of functiotructuren pointers, each of the function is routine for performing a specific operation over the device like read, write ,open, close etc. Another one is struct inode(for the device file). We all know everything in linux is treated as a file, some are regular files and some are special files. A character device is treated as a special file in our system. Attributes of a file are stored in the structure struct inode and struct inode i am talking about have attribues of that special file for the character device. Fourth one is struct file. struct file is a structure which containes the attributes of a stream. This stream is a stream created between our app and node in vfs, when we give an open call from app.
I have allocated some memory in the kernel space of my RAM in form of SCULL(Simple Character Utility for Loading Localities), which i am treating as a device. This memory is variable as i will be performing write and read, it will be allocated and deallocated accordingly. Starting node of this memory is ScullDev which will be loaded with the lot of info about the device like device_size, data_size, quantum_size, qset_size, write_count and the most important an object of struct cdev. We need to initialize and add this cdev object as our device in the kernel using two MACROS cdev_init() and cdev_add(). cdev_init will initialize our object for the set of operations and cdev_add will add this device in to the device table.
After all this, my device is ready to be worked upon i.e open,write,read,close. For this it was required to map my driver routines to the routines called by system as when a call is given from app my routines should run in the driver. This mapping is to be done in struct file_operations by giving the addresses of my_routines to corresponding function pointers in fops. In open i fetched the address of my ScullDev for the perticular cdev and stored it in private_data field of a system genrated structure struct file pointed by *filep in open for the future use of this address in write and read.
Now i am able to write data to the multiple quantums, multiple scullqset in trunc as well as append mode. I am able to read from the same as well. lseek is also done, and i have tested my driver for multithreaded apps, using various synchronization techniques.

Posted in Uncategorized | Leave a comment

Pointer->>>>>>>>>>>>>>

Introduction:->Pointer

 

A pointer is a variable that contains the address of a variable. Pointers are much used in C,

partly because they are sometimes the only way to express a computation, and partly because

they usually lead to more compact and efficient code than can be obtained in other ways.

Pointers and arrays are closely related; this chapter also explores this relationship and shows

how to exploit it.

 

This is certainly true when they are used carelessly, and it is easy to create pointers that point somewhere unexpected. With discipline, however, pointers can also be used to achieve clarity and simplicity. This is the aspect that we will try to illustrate.

 

The main change in ANSI C is to make explicit the rules about how pointers can be

manipulated, in effect mandating what good programmers already practice and good compilers

already enforce. In addition, the type void * (pointer to void) replaces char * as the proper

type for a generic pointer.

 

Pointers and Addresses:-

 

Let us begin with a simplified picture of how memory is organized. A typical machine has an

array of consecutively numbered or addressed memory cells that may be manipulated

individually or in contiguous groups. One common situation is that any byte can be a char, 4 byte cells can be treated as a short integer, and 8 adjacent bytes form a long. A

pointer is a group of cells (often two or four) that can hold an address.

So if c is a char and p is a pointer that points to it, we could represent the situation this way:

 

The unary operator & gives the address of an object, so the statement

 

p = &c;

 

assigns the address of c to the variable p, and p is said to “point to” c. The & operator only

applies to objects in memory: variables and array elements. It cannot be applied to expressions,

constants, or register variables.

The unary operator * is the indirection or dereferencing operator; when applied to a pointer, it

accesses the object the pointer points to. Suppose that x and y are integers and ip is a pointer

to int. This artificial sequence shows how to declare a pointer and how to use & and *:

int x = 1, y = 2, z[10];

int *ip; /* ip is a pointer to int */

ip = &x; /* ip now points to x */

y = *ip; /* y is now 1 */

*ip = 0; /* x is now 0 */

ip = &z[0]; /* ip now points to z[0] */

The declaration of x, y, and z are what we’ve seen all along.

 

Pointers and Arrays:-

 

In C, there is a strong relationship between pointers and arrays, strong enough that pointers

and arrays should be discussed simultaneously. Any operation that can be achieved by array

subscripting can also be done with pointers. The pointer version will in general be faster but, at

least to the uninitiated, somewhat harder to understand.

The declaration

int a[10];

defines an array of size 10, that is, a block of 10 consecutive objects named a[0], a[1],

…,a[9].

 

The notation a[i] refers to the i-th element of the array. If pa is a pointer to an integer,

declared as

int *pa;

then the assignment

pa = &a[0];

sets pa to point to element zero of a; that is, pa contains the address of a[0].

Now the assignment

x = *pa;

will copy the contents of a[0] into x.

If pa points to a particular element of an array, then by definition pa+1 points to the next

element, pa+i points i elements after pa, and pa-i points i elements before. Thus, if pa points

to a[0],

*(pa+1)

refers to the contents of a[1], pa+i is the address of a[i], and *(pa+i) is the contents of

a[i].

 

These remarks are true regardless of the type or size of the variables in the array a. The

meaning of “adding 1 to a pointer,” and by extension, all pointer arithmetic, is that pa+1 points

to the next object, and pa+i points to the i-th object beyond pa.

The correspondence between indexing and pointer arithmetic is very close. By definition, the

value of a variable or expression of type array is the address of element zero of the array. Thus

after the assignment

pa = &a[0];

pa and a have identical values. Since the name of an array is a synonym for the location of the

initial element, the assignment pa=&a[0] can also be written as

pa = a;

Rather more surprising, at first sight, is the fact that a reference to a[i] can also be written as

*(a+i). In evaluating a[i], C converts it to *(a+i) immediately; the two forms are

equivalent. Applying the operator & to both parts of this equivalence, it follows that &a[i] and

a+i are also identical: a+i is the address of the i-th element beyond a. As the other side of this

coin, if pa is a pointer, expressions might use it with a subscript; pa[i] is identical to *(pa+i).

In short, an array-and-index expression is equivalent to one written as a pointer and offset.

There is one difference between an array name and a pointer that must be kept in mind. A

pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable;

constructions like a=pa and a++ are illegal.

When an array name is passed to a function, what is passed is the location of the initial

element. Within the called function, this argument is a local variable, and so an array name

parameter is a pointer, that is, a variable containing an address. We can use this fact to write

another version of strlen, which computes the length of a string.

/* strlen: return length of string s */

int strlen(char *s)

{

int n;

for (n = 0; *s != ”, s++)

n++;

return n;

}

Since s is a pointer, incrementing it is perfectly legal; s++ has no effect on the character string

in the function that called strlen, but merely increments strlen’s private copy of the pointer.

That means that calls like

strlen(“hello, world”); /* string constant */

strlen(array); /* char array[100]; */

strlen(ptr); /* char *ptr; */

all work.

 

Posted in Uncategorized | Leave a comment

Article:Description of USB Device Enumeration

Introduction
USB Enumeration is the process of detecting, identifying and loading drivers for a USB device.This involves a mixture of hardware techniques for detecting something is present and software to identify what has been connected.
The purpose of this article is to provide an overview of the mechanics of the process
Detecting a Device has been Connected

A USB interface consists of 4 wires. Power, Ground, Data Plus (USBDP) and Data Minus (USBDM). A USB host port with no devices connected uses 15kohm resistors to connect both USB DP and USB DM to GND. When a USB device (sometimes referred to as a slave) is plugged into a USB host there is a change on these USB data lines. It is this change that the USB host uses to detect a device has been connected.This change is also used to identify the speed of device attached.

Determining the Device Speed
A low speed USB device (1.5Mbps) uses a 1k5 pull-up resistor to VCC on the USB DM signal line.
A full speed USB device (12Mbps) uses a 1k5 pull-up resistor to VCC on the USB DP signal line.
A high speed USB device (480Mbps) will initially appear as a full speed device to the host. The first thing the USB host does is to attempt to send /receive packets at high speed to the USB device. This is known as J and K chirp and if communication is successful it will be assumed that the USB device is a high speed device. If this initial communication fails then the USB host assumes that the device is a full speed device. This means a high speed device has a 1k5 pull up resistor on USB DP that can be switched in / out of circuit

Determining What Device is Attached (Device Descriptor)
Devices are identified by descriptors. Once the USB host has established a USB device is connected, and at what speed it should communicate,then the host will reset the USB device and attempt to read the descriptors to identify the USB device using a default address.
This basically follows a question and answer process. The USB host will send a Get_Device_Descriptor command and then receive a packet of bytes with the descriptor length and the actual descriptor. At the completion of this stage the device is reset and given a unique address before getting the configuration and interface descriptors.

bLength.
All USB devices have descriptors and the first key one is the Device Descriptor. The length is 18 bytes
and it is bDdescriptorType is type 1.

bcdUSB.
This is used to identify the device as a USB 1.0, USB 1.1 or USB 2.0 compliant device

bDeviceClass, bDeviceSubClass and bProtocol
The bDeviceClass of device defines the device type e.g. a USB Mouse is a Human Interface Device (HID)
class device. This is given a hex value of 0×03.More complex devices such as Communication Device Class (CDC) may also use a sub class to break down the device type into a smaller group.

bMaxPacketSize
This defines the maximum number of bytes in a packet from an endpoint

idVendor and idProduct
The idVendor (VID) is assigned to a company by the USB Implementers Forum. An idProduct (PID) is used with this value to help associate a device with a manufacturer and product. It is also used to help link the hardware with a specific driver.
iManufacturer, iProduct and iSerialNumber
These values are indexes to the Manufacturer string, the Product name string, and the Serial Number strings. These descriptors help make the identifiers more human readable and can be of variable length.

Posted in Uncategorized | Leave a comment

article on socket programming

ARTICLE ON SOCKET PROGRAMMING [LINUX]

A LINUX socket (inter-process communication socket) is a data communications endpoint for exchanging data between processes WHICH allow one process to communicate with another whether it is local on the same computer system or remote over the network. Many other higher level protocols are built upon sockets technology.
Sockets utilize the following standard protocols:

Protocol Description
IP Internet Protocol provides network routing using IP addressing eg 192.168.1.204
UDP User Datagram Protocol – IP with ports to distinguish among processes running on same host. No data verification.
TCP Transmission Control Protocol – IP with ports to distinguish among processes running on same host.Connection oriented, stream
transfer, full duplex, reliable with data verification.

Typically one configures a socket server to which a socket client may attach and communicate.
Create the socket instance.
IN THIS THE STEPS ARE DESCRIBED HOW WE CREATE SOCKET & HOW SERVER AND CLINT INTERACT WITH EACH OTHER.
1-Socket function prototype:
int sockfd = socket(int socket_family, int socket_type, int protocol)
discription: Choose socket communications family/domain
according to the communication within same host or over the network we choose the family as AF_UNIX,OR AF_INET ACCORDINGLY.

Choose socket type:

TCP: SOCK_STREAM for connection oriented services using tcp protocol.
UDP: SOCK_DGRAM for connectionless services using UDP protocol.

Choose socket protocol: (See /etc/protocols)
for AF_UNIX & AF_INET or Internet Protocol (IP): 0 or IPPROTO_IP
for ICMP: 1
2-Configure the socket as a client or server:
Socket Server            Socket Client
socket()                      socket()
bind()
listen()
accept()                        connect()
recv()/send()            recv()/send()
close() close()
This is specific to whether the application is a socket client or a socket server.
above all calls are listed which we use in socket as server & clint configuration.
the detail discription of calls are as…
Socket server:
bind(): bind the socket to a local socket address. This assigns a name to the socket.Function prototype:
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
Bind arguments:
int sockfd: Socket file descriptor. Returned by call to “socket”.
struct sockaddr: Socket information structure
socklen_t addrlen: Size of structure
Returns 0: Sucess, -1: Failure and errno may be set.
listen(): listen for connections on a socket created with “socket()” and “bind()” and accept incoming connections. This is used for TCP and not UDP. Zero is returned on success.Function prototype:
int listen(int s, int backlog);
Listen arguments:
int s: Socket file descriptor. Returned by call to “socket”. Identifies a bound but unconnected socket.
int backlog: Set maximum length of the queue of pending connections for the listening socket. A reasonable value is 10. Actual maximum permissible: SOMAXCONN .
accept(): accept a connection on a socket. Accept the first connection request on the queue of pending connections, create a new connected socket with mostly the same properties as defined by the call to “socket()”, and allocate a new file descriptor for the socket, which is returned. The newly created socket is no longer in the listening state. Note this call blocks until a client connects.
Function prototype:
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
Accept arguments:
int s: Socket file descriptor. Returned by call to “socket”.
struct sockaddr *addr: Pointer to a sockaddr structure. This structure is filled in with the address of the connecting entity.
socklen_t *addrlen: initially contains the size of the structure pointed to by addr; on return it will contain the actual length (in bytes) of the address returned. When addr is NULL nothing is filled in.
Returns:
Success: non-negative integer, which is a descriptor of the accepted socket. Argument “addrlen” will have a return value.
Fail: -1, errno may be set

Socket client:
connect(): initiate a connection with a remote entity on a socket. Zero is returned on success. Support both TCP (SOCK_STREAM) and UDP (SOCK_DGRAM). For SOCK_STREAM, an actual connection is made. For SOCK_DGRAM the address is the address to which datagrams are sent and received.
Connect function prototype:
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
Connect arguments: (Same as server’s bind() arguments)
int sockfd: Socket file descriptor. Returned by call to “socket”.
struct sockaddr: Socket information structure
socklen_t addrlen: Size of structure
Returns 0: Sucess, -1: Failure and errno may be set.
Zero is returned upon success and on error, -1 and errno is set appropriately.

here description of sockaddr_in data structure that how we name & provide address to socket.

socketInfo.sin_family = AF_INET;
// Use any address available to the system. This is a typical configuration for a server.
// Note that this is where the socket client and socket server differ.
// A socket client will specify the server address to connect to.
socketInfo.sin_addr.s_addr = htonl(“ip addd”); // Translate long integer to network byte order.
socketInfo.sin_port = htons(portNumber); // Set port number

so this is all about socket programming in brief….

Posted in Uncategorized | Leave a comment

Usb devices type ,transfer type in usb and enumeration article

Here We are discuss about the usb devices in this very document

USB is a master-slave protocol where a host controller communicates with client devices. The USB host controller is part of the South Bridge chipset and communicates with
the processor over the PCI bus.

Usb types :-

Usb types Connectors bases :-

There are four basic kinds or sizes related to the USB connectors
1. The older “standard” size, in its USB 1.1/2.0 and USB 3.0 variants eg. usb pendrive
2. The “mini” size (primarily for the B connector ) e.g. Cemra
3. The “micro” size, in its USB 1.1/2.0 and USB 3.0 variants eg. In mobile phone .
4. USB On The Go scheme, in both mini and micro sizes.

Usb types Speed bases :-

1. USB 1.x
USB 1 specified data rates of 1.5 Mbits/s Low-Bandwidth and 12 Mbits/s Full-Bandwidth. It is generally white color.
2. USB 2.0
USB 2.0 is adding higher maximum signaling rate of 480 Mbits Hi-Speed.USB 2.0 connectors are black.

3. USB 3.0
The standard defines a new Super Speed mode with a signaling speed of 5Gbits/s. USB 3.0 port is usually colored blue, and is backwards compatible with USB 2.0

Host Controllers
:-
USB host controllers conform to one of a few standards:

Universal Host Controller Interface (UHCI): The UHCI specification was initiated by Intel, so our
is likely to have this controller if it’s Intel-based.
Open Host Controller Interface (OHCI): The OHCI specification originated from companies such as
Compaq and Microsoft. An OHCI-compatible controller has more intelligence built in to hardware than
UHCI, so an OHCI HCD is relatively simpler than a UHCI HCD.
Enhanced Host Controller Interface (EHCI): This is the host controller that supports high-speed USB
2.0 devices. EHCI controllers usually have either a UHCI or OHCI companion controller to handle slower
devices.
USB OTG controllers: They are getting increasingly popular in embedded microcontrollers. With OTG
support, each communicating end can act as a dual-role device (DRD).

eXtensible Host Controller Interface (xHCI): This is a computer interface specification that defines a register-level description of a Host Controller for Universal Serial bus (USB), which is capable of interfacing to USB 1.x, 2.0, and 3.0 compatible devices. The specification is also referred to as the
USB 3.0 Host Controller

you can check host controllers by the following command
[root@localhost ubh3b]# lspci
00:00.0 Host bridge: Intel Corporation Ivy Bridge DRAM Controller (rev 09)
00:01.0 PCI bridge: Intel Corporation Ivy Bridge PCI Express Root Port (rev 09)
00:01.1 PCI bridge: Intel Corporation Ivy Bridge PCI Express Root Port (rev 09)
00:02.0 VGA compatible controller: Intel Corporation Device 0166 (rev 09)
00:14.0 USB Controller: Intel Corporation Panther Point USB xHCI Host Controller (rev 04)
00:16.0 Communication controller: Intel Corporation Panther Point MEI Controller #1 (rev 04)
00:1a.0 USB Controller: Intel Corporation Panther Point USB Enhanced Host Controller #2 (rev 04)
00:1b.0 Audio device: Intel Corporation Panther Point High Definition Audio Controller (rev 04)
00:1c.0 PCI bridge: Intel Corporation Panther Point PCI Express Root Port 1 (rev c4)
00:1c.1 PCI bridge: Intel Corporation Panther Point PCI Express Root Port 2 (rev c4)
00:1d.0 USB Controller: Intel Corporation Panther Point USB Enhanced Host Controller #1 (rev 04)
00:1f.0 ISA bridge: Intel Corporation Panther Point LPC Controller (rev 04)
00:1f.2 SATA controller: Intel Corporation Panther Point 6 port SATA AHCI Controller (rev 04)
00:1f.3 SMBus: Intel Corporation Panther Point SMBus Controller (rev 04)
01:00.0 3D controller: nVidia Corporation Device 1140 (rev a1)
03:00.0 Ethernet controller: Atheros Communications Device 1090 (rev 10)
04:00.0 Network controller: Atheros Communications Inc. AR9485 Wireless Network Adapter (rev 01)

Transfer Types
:-
Data exchange with a USB device can be one of four types:
1. Control transfers :- used to carry configuration and control information
2. Bulk transfers :-that ferry large quantities of time-insensitive data
3. Interrupt transfers:- that exchange small quantities of time-sensitive data
4. Isochronous transfers :- for real-time data at predictable bit rates

A USB storage drive, for example, uses control transfers to issue disk access commands and bulk transfers to exchange data. A keyboard uses interrupt transfers to carry key strokes within predictable delays. A device that
needs to stream audio data in real time uses isochronous transfers.

Addressing
Each addressable unit in a USB device is called an endpoint. The address assigned to an endpoint is called an
endpoint address. Each endpoint address has an associated data transfer type. If an endpoint is responsible for
bulk data transfer, for example, it’s called a bulk endpoint. Endpoint address 0 is used exclusively for device
configuration. A control pipe is attached to this endpoint for device enumeration.
Enumeration
The life of a hotplugged USB device starts with a process called enumeration by which the host learns about the
device’s capabilities and configures it. The hub driver is the component in the Linux-USB subsystem responsible
for enumeration. Let’s look at the sequence of steps that achieve device enumeration when you plug in a USB
pen drive into a host computer:
1. The root hub reports a change in the port’s current due to the device attachment. The hub driver detects
this status change, called a USB_PORT_STAT_C_CONNECTION in Linux-USB terminology, and awakens khubd.
2. Khubd deciphers the identity of the USB port subjected to the status change. In this case, it’s the port
where you plugged in the pen drive.
3. Next, khubd chooses a device address between 1 and 127 and assigns it to the pen drive’s bulk endpoint
using a control URB attached to endpoint 0.
4. Khubd uses the above control URB attached to endpoint 0 to obtain the device descriptor from the pen
drive. It then requests the device’s configuration descriptors and selects a suitable one. In the case of the
pen drive, only a single configuration descriptor is on offer.
5. Khubd requests the USB core to bind a matching client driver to the inserted device.
When enumeration is complete and the device is bound to a driver, khubd invokes the associated client driver’s
probe() method. In this case, khubd calls storage_probe() defined in drivers/usb/storage/usb.c. From this
point on, the mass storage driver is responsible for normal device operation.

Posted in Uncategorized | Leave a comment

C Programming

A C programming based Project C language is the general purpose programming language developed by Dennis Ritchie. C language is the base of many other languages like C#, Java, Python, Perl, PHP. C has facilities like structure programming, functional programming. There are some standard made for C programming. C also allows the most precise control of input and output. There is a project name by Multiple Data Compression using iterative techniques. While working on this project i implemented all my knowledge regarding C language.

“Multiple Data Compression and Encryption using Iterative techniques”. The basic concept of this project is to compress a text file and encrypt it so that unauthorized person cannot understand it. This project compress a text file and reduce the size of the text file. While making the source code for this program I implement all the concept of C language and project management tools.

In C Programming based Project I started with basic of C programming that is how a code or source file is compiled by gcc compiler and then how it will run. After that i learn in C language is their data types, ranges of various data types, how they will access in the program, libraries used in C program, how to write a simple program in C. After the basic knowledge of C programming, I studied about the operator used in C programming. How to use control structure like conditional statements (if, if-else, nested if, switch) and then looping statement (for, while, do-while). Then I studied array that is collection of elements of same data types in contiguous memory allocation and string that is collection of character ending with a null character (”). Then I started with pointers which stores address of a variable. I implement various program which clears my concept of pointer and reference because it is most important thing in C programming. After the pointer I studied structure that is the collection of variable of different data types in contiguous memory location. By using structure I implement link list, stacks, queues and circular queues. After the structure I studied file IO that is used to open a file and perform reading writing operation through programming. In file IO, I learn both low level and high file IO. Then i started with the various sorting and searching techniques like linear and binary searching, bubble, selection, insertion, quick, heap sorting. I also perform their practical implementation. Then i started with the project management tools which i also implement during my practical implementation of C programs. There are various project management tools which I studied like make file (which is used to compile multiple targets), rcs (Revision Control System-which is used to save our work when we make some changes and helps in retrieving the previous version of source code in which I made changes), cvs(Concurrent Version System- is comes over the disadvantages of rcsand is done over internet). Also I studied the debugging tool that is gdb which helps in checking the error in the program during execution. I implement various programs and assignment related to the C Programming.

Posted in Uncategorized | Leave a comment