Device Drivers


Published on

Basic Information related to device driver including char device and block device.

  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Device Drivers

  2. 2. Introduction• Defination :- Device driver or software driver is a computer program allowing higher-level computer programs to interact with a hardware device.• A driver typically communicates with the device through the computer bus or communications subsystem to which the hardware connects.• Drivers are hardware-dependent and operating- system-specific. They usually provide the interrupt handling required for any necessary asynchronous time-dependent hardware interface.
  3. 3. Why a Device Driver?• A device driver is usually part of the OS kernel o Compiled with the OS o Dynamically loaded into the OS during execution.• Each device driver handles o one device type (e.g., mouse) o one class of closely related devices (e.g., SCSI disk driver to handle multiple disks of different sizes and different speeds.).• A device driver simplifies programming by acting as translator between a hardware device and the applications or operating systems that use it.• Programmers can write the higher-level application code independently of whatever specific hardware device.
  4. 4. Location
  5. 5. Device Drivers in Linux
  6. 6. Processes in Linux• When a user process executes a system call, it does not transfer control to another process,• but changes its execution mode from user to kernel mode.• In kernel mode, while executing the system call, the process has access to the kernel address space, and• Through supporting functions it has access to the address space of the user executing the call.
  7. 7. Functions in Device Drivers• Accept abstract read and write requests from the device-independent layer above.• Initialize the device.• Manage power requirements and log events.• Check input parameters if they are valid.• Translate valid input from abstract to concrete terms o e.g., convert linear block number into the head, track, sector and cylinder number for disk access.• Check the device if it is in use (i.e., check the status bit).• Control the device by issuing a sequence of commands. The driver determines what commands will be issued.
  8. 8. Loadable Kernel Module• In computing, a loadable kernel module (or LKM) is an object file that contains code to extend the running kernel, or so- called base kernel, of an operating system.• Most current Unix-like systems, and Microsoft Windows, support loadable kernel modules.• Without loadable kernel modules, an operating system would have to have all possible anticipated functionality already compiled directly into the base kernel.• Much of that functionality would reside in memory without being used, wasting memory, and would require that users rebuild and reboot the base kernel every time new functionality is desired.• Most operating systems supporting loadable kernel modules will include modules to support most desired functionality.
  9. 9. Classes of Devices and Modules• The Linux way of looking at devices distinguishes between three fundamental device types.• Each module usually implements one of these types, and thus is classifiable as 1.char module 2.block module module.
  10. 10. 1. Character devices• A character (char) device is one that can be accessed as a stream of bytes (like a file); a char driver is in charge of implementing this behavior.• Such a driver usually implements at least the open, close, read, and write system calls.• The text console (/dev/console) and the serial ports (/dev/ttyS0 and friends) are examples of char devices, as they are well represented by the stream abstraction.• Char devices are accessed by means of filesystem nodes, such as /dev/tty1 and /dev/lp0.• 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.
  11. 11. 2.Block devices• Like char devices, block devices are accessed by filesystem nodes in the /dev directory.• A block device is a device (e.g., a disk) that can host a filesystem.• In most Unix systems, a block device can only handle I/O operations that transfer one or more whole blocks, which are usually 512 bytes (or a larger power of two) bytes in length.• Linux, instead, allows the application to read and write a block device like a char device—it permits the transfer of any number of bytes at a time.• As a result, block and char devices differ only in the way data is managed internally by the kernel, and thus in the kernel/driver software interface.• Like a char device, each block device is accessed through a filesystem node, and the difference between them is transparent to the user.
  12. 12. 3. Network interfaces• Any network transaction is made through an interface, that is, a device that is able to exchange data with other hosts.• Usually, an interface is a hardware device, but it might also be a pure software device, like the loopback interface.• A network interface is in charge of sending and receiving data packets, driven by the network subsystem of the kernel, without knowing how individual transactions map to the actual packets being transmitted.• Many network connections (especially those using TCP) are stream-oriented, but network devices are, usually, designed around the transmission and receipt of packets.• A network driver knows nothing about individual connections; it only handles packets.
  13. 13. Major Minor Numbers• Major device numbers are used by the Linux system to map I/O requests to the driver code, thereby deciding which device driver to execute, when a user reads from or writes to the special file.• The minor numbers are entirely under the control of the driver writer, and usually refer to sub-devices of the device.• These sub-devices may be separate units attached to a controller. Thus, a disk device driver may, for example, communicate with a hardware controller (the device) which has several disk drives (sub- devices) attached.
  14. 14. Device Driver Protocolo After driver knows which commands to issue, it starts to write them into controllers device registers .o After writing each command, it checks to see if the controller accepted the command and is prepared to accept the next one.o After commands have been issued, either (a) the device waits until the controller does some work and it blocks itself until interrupt comes to unblock it; or (b) the device doesnt wait because the command finished without any delay.
  15. 15. Applications• Because of the diversity of modern hardware and operating systems, drivers operate in many different environments. Drivers may interface with:• Printers• video adapters• network cards• sound cards• local buses of various sorts — in particular, for bus mastering on modern systems• low-bandwidth I/O buses of various sorts (for pointing devices such as mice, keyboards, USB, etc.)• computer storage devices such as hard disk, CD-ROM and floppy disk buses (ATA, SATA, SCSI)• implementing support for different file systems• image scanners• digital cameras
  16. 16. Character Device Driver• User Space and Kernel Space• Loading and Removing the driver in user space• Loading and Removing the driver in kernel space• The complete driver “memory”
  17. 17. User space and kernel space• When you write device drivers, it’s important to make the distinction between “user space” and “kernel space”.• Kernel Space : Linux (which is a kernel) manages the machines hardware in a simple and efficient manner, offering the user a simple and uniform programming interface.• In the same way, the kernel, and in particular its device drivers, form a bridge or interface between the end-user/programmer and the hardware.• Any subroutines or functions forming part of the kernel (modules and device drivers, for example) are considered to be part of kernel space.
  18. 18. • User space : End-user programs, like the UNIX shell or other GUI based applications (kpresenter for example), are part of the user space. • Obviously, these applications need to interact with the systems hardware . However, they don’t do so directly, but through the kernel supported functions.Device driver events and their associated interfacing functions between kernel space and user space.Events User functions Kernel functionsLoad module insmod module_init()Open device fopen file_operations: openClose device fread file_operations: readWrite device fwrite file_operations: writeClose device fclose file_operations: releaseRemove module rmmod module_exit()Device driver events and their associated functions between kernel space and the hardware device.Events Kernel functionsRead data inbWrite data outb
  19. 19. Loading and Removing the driver in user space• To implement simple character device driver in user space make one file named “demo.c” and content of file is : #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL");• Next, you need to generate a makefile. The makefile for this example, which should be named Makefile, will be: obj-m := demo.o• Unlike with previous versions of the kernel, it’s now also necessary to compile the module using the same kernel that you’re going to load and use the module with. To compile it, you can type: make -C /usr/src/kernel-source-2.6.8 M=`pwd` modules
  20. 20. In user space, you can load the module as root by typing the followinginto the command line:# insmod demo.koThe insmod command allows the installation of the module in the kernel.However, this particular module isn’t of much use.It is possible to check that the module has been installed correctly bylooking at all installed modules:# lsmodFinally, the module can be removed from the kernel using the command:# rmmod demoBy issuing the lsmod command again, you can verify that the module isno longer in the kernel.
  21. 21. Loading and Removing the driver in kernel space • When a module device driver is loaded into the kernel, some preliminary tasks are usually performed like resetting the device, reserving RAM, reserving interrupts, and reserving input/output ports, etc. • These tasks are performed, in kernel space, by two functions which need to be present (and explicitly declared): module_init and module_exit; they correspond to the user space commands insmod and rmmod , which are used when installing or removing a module. • To sum up, the user commands insmod and rmmod use the kernel space functions module_init and module_exit.
  22. 22. #include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>MODULE_LICENSE("Dual BSD/GPL");static int hello_init(void){ printk("<1> Hello world!n"); return 0;}static void hello_exit(void){ printk("<1> Bye, cruelworldn");}module_init(hello_init);module_exit(hello_exit);
  23. 23. • The actual functions hello_init and hello_exit can be given any name desired. However, in order for them to be identified as the corresponding loading and removing functions, they have to be passed as parameters to the functions module_init and module_exit.• The printk function has also been introduced. It is very similar to the well known printf apart from the fact that it only works inside the kernel. The <1> symbol shows the high priority of the message (low number). In this way, besides getting the message in the kernel system log files, you should also receive this message in the system console.• This module can be compiled using the same command as before, after adding its name into the Makefile and content of it is : “obj-m := demo.o hello.o”.
  24. 24. The complete driver “memory”: initial part of the driver• I’ll now show how to build a complete device driver: memory.c. This device will allow a character to be read from or written into it. This device, while normally not very useful, provides a very illustrative example since it is a complete driver; its also easy to implement,since it doesn’t interface to a real hardware device.• After the #include files, the functions that will be defined later are declared.• The common functions which are typically used to manipulate files are declared in the definition of the file_operations structure. These will also be explained in detail later. Next, the initialization and exit functions—used when loading and removing the module—are declared to the kernel.• Finally, the global variables of the driver are declared: one of them is the major number of the driver, the other is a pointer to a region in memory, memory_buffer, which will be used as storage for the driver data.
  25. 25. /* Necessary includes for device drivers */#include <linux/init.h>#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h> /* printk() */#include <linux/slab.h> /* kmalloc() */#include <linux/fs.h> /* everything... */#include <linux/errno.h> /* error codes */#include <linux/types.h> /* size_t */#include <linux/proc_fs.h>#include <linux/fcntl.h> /* O_ACCMODE */#include <asm/system.h> /* cli(), *_flags */#include <asm/uaccess.h> /* copy_from/to_user */MODULE_LICENSE("Dual BSD/GPL");/* Declaration of memory.c functions */int memory_open(struct inode *inode, struct file *filp);int memory_release(struct inode *inode, struct file *filp);ssize_t memory_read(struct file *filp, char *buf, size_t count, loff_t*f_pos);ssize_t memory_write(struct file *filp, char *buf, size_t count, loff_t*f_pos);void memory_exit(void);int memory_init(void);/* Structure that declares the usual file *//* access functions */struct file_operations memory_fops = { read: memory_read, write: memory_write, open: memory_open, release: memory_release};/* Declaration of the init and exit functions */module_init(memory_init);module_exit(memory_exit);/* Global variables of the driver *//* Major number */int memory_major = 60;/* Buffer to store data */char *memory_buffer;
  26. 26. The “memory” driver: connection of the device with its files• In UNIX and Linux, devices are accessed from user space in exactly the same way as files are accessed. These device files are normally subdirectories of the /dev directory.• To link normal files with a kernel module two numbers are used: major number and minor number. The major number is the one the kernel uses to link a file with its driver. The minor number is for internal use of the device and for simplicity it won’t be covered in this article.• To achieve this, a file (which will be used to access the device driver) must be created, by typing the following command as root:• # mknod /dev/memory c 60 0• In the above, c means that a char device is to be created, 60 is the major number and 0 is the minor number.• Within the driver, in order to link it with its corresponding /dev file in kernel space, the register_chrdev function is used. It is called with three arguments: major number, a string of characters showing the module name, and a file_operations structure which links the call with the file functions it defines. It is invoked, when installing the module, in this way:• Also, note the use of the kmalloc function. This function is used for memory allocation of the buffer in the device driver which resides in kernel space. Its use is very similar to the well known malloc function. Finally, if registering the major number or allocating the memory fails, the module acts accordingly.
  27. 27. int memory_init(void) { int result; /* Registering device */ result = register_chrdev(memory_major, "memory", &memory_fops); if (result < 0) { printk( "<1>memory: cannot obtain major number %dn", memory_major); return result; } /* Allocating memory for the buffer */ memory_buffer = kmalloc(1, GFP_KERNEL); if (!memory_buffer) { result = -ENOMEM; goto fail; } memset(memory_buffer, 0, 1); printk("<1>Inserting memory modulen"); return 0; fail: memory_exit(); return result;}
  28. 28. The “memory” driver: removing the driver• In order to remove the module inside the memory_exit function, the function unregsiter_chrdev needs to be present. This will free the major number for the kernel.• The buffer memory is also freed in this function, in order to leave a clean kernel when removing the device driver. void memory_exit(void) { /* Freeing the major number */ unregister_chrdev(memory_major, "memory"); /* Freeing buffer memory */ if (memory_buffer) { kfree(memory_buffer); } printk("<1>Removing memory modulen"); }
  29. 29. The “memory” driver: opening the device as a file• The kernel space function, which corresponds to opening a file in user space (fopen), is the member open: of the file_operations structure in the call to register_chrdev. In this case, it is the memory_open function. It takes as arguments: an inode structure, which sends information to the kernel regarding the major number and minor number; and a file structure with information relative to the different operations that can be performed on a file. Neither of these functions will be covered in depth within this article.• When a file is opened, it’s normally necessary to initialize driver variables or reset the device. In this simple example, though, these operations are not performed.• The memory_open function can be seen below: int memory_open(struct inode *inode, struct file *filp) { /* Success */ return 0; }
  30. 30. The “memory” driver: closing the device as a file• The corresponding function for closing a file in user space (fclose) is the release: member of the file_operations structure in the call to register_chrdev. In this particular case, it is the function memory_release, which has as arguments an inode structure and a file structure, just like before.• When a file is closed, it’s usually necessary to free the used memory and any variables related to the opening of the device. But, once again, due to the simplicity of this example, none of these operations are performed.• The memory_release function is shown below: int memory_release(struct inode *inode, struct file *filp) { /* Success */ return 0; }
  31. 31. The “memory” driver: reading the device• To read a device with the user function fread or similar, the member read: of the file_operations structure is used in the call to register_chrdev. This time, it is the function memory_read. Its arguments are: a type file structure; a buffer (buf), from which the user space function (fread) will read; a counter with the number of bytes to transfer (count), which has the same value as the usual counter in the user space function (fread); and finally, the position of where to start reading the file (f_pos).• In this simple case, the memory_read function transfers a single byte from the driver buffer (memory_buffer) to user space with the function copy_to_user:
  32. 32. ssize_t memory_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) { /* Transfering data to user space */ copy_to_user(buf,memory_buffer,1); /* Changing reading position as best suits */ if (*f_pos == 0) { *f_pos+=1; return 1; } else { return 0; }} • The reading position in the file (f_pos) is also changed. If the position is at the beginning of the file, it is increased by one and the number of bytes that have been properly read is given as a return value, 1. If not at the beginning of the file, an end of file (0) is returned since the file only stores one byte.
  33. 33. The “memory” driver: writing to a device • To write to a device with the user function fwrite or similar, the member write: of the file_operations structure is used in the call to register_chrdev. • It is the function memory_write, in this particular example, which has the following as arguments: a type file structure; buf, a buffer in which the user space function (fwrite) will write; count, a counter with the number of bytes to transfer, which has the same values as the usual counter in the user space function (fwrite); and finally, f_pos, the position of where to start writing in the file.ssize_t memory_write( struct file *filp, char *buf, size_t count, loff_t *f_pos) { char *tmp; tmp=buf+count-1; copy_from_user(memory_buffer,tmp,1); return 1;}
  34. 34. The complete “memory” driver• By joining all of the previously shown code, the complete driver is achieved: <memory.c> = <memory initial> <memory init module> <memory exit module> <memory open> <memory release> <memory read> <memory write>• Before this module can be used, you will need to compile it in the same way as with previous modules. The module can then be loaded with:• # insmod memory.ko• It’s also convenient to unprotect the device:• # chmod 666 /dev/memory• If everything went well, you will have a device /dev/memory to which you can write a string of characters and it will store the last one of them. You can perform the operation like this:• $ echo -n abcdef >/dev/memory• To check the content of the device you can use a simple cat:• $ cat /dev/memory• The stored character will not change until it is overwritten or the module is removed.
  35. 35. USB Drivers• The universal serial bus (USB) is a connection between a host computer and a number of peripheral devices.• It was originally created to replace a wide range of slow and different buses—the parallel, serial, and keyboard connections—with a single bus type that all devices could connect to.• USB has grown beyond these slow connections and now supports almost every type of device that can be connected to a PC.• The latest revision of the USB specification added high-speed connections with a theoretical speed limit of 480 MBps.
  36. 36. • Topologically, a USB subsystem is not laid out as a bus; it is rather a tree built out of several point-to-point links. The links are four-wire cables (ground, power, and two signal wires) that connect a device and a hub, just like twisted-pair Ethernet.• The USB host controller is in charge of asking every USB device if it has any data to send.• Because of this topology, a USB device can never start sending data without first being asked to by the host controller.• This configuration allows for a very easy plugand-play type of system, whereby devices can be automatically configured by the host computer.
  37. 37. • The USB protocol specifications define a set of standards that any device of a specific type can follow.• If a device follows that standard, then a special driver for that device is not necessary.• These different types are called classes and consist of things like storage devices, keyboards, mice, joysticks, network devices, and modems.• Other types of devices that do not fit into these classes require a special vendor-specific driver to be written for that specific device.• Video devices and USB-to-serial devices are a good example where there is no defined standard, and a driver is needed for every different device from different manufacturers.
  38. 38. USB Device Basics• A USB device is a very complex thing, as described in the official USB documentation (available at• Fortunately, the Linux kernel provides a subsystem called the USB core to handle most of the complexity. This chapter describes the interaction between a driver and the USB core.• USB devices consist of configurations, interfaces, and endpoints and how USB drivers bind to USB interfaces, not the entire USB device.
  39. 39. 1. Endpoints• The most basic form of USB communication is through something called an endpoint.• A USB endpoint can carry data in only one direction, either from the host computer to the device (called an OUT endpoint) or from the device to the host computer (called an IN endpoint).• Endpoints can be thought of as unidirectional pipes.• A USB endpoint can be one of four different types that describe how the data is transmitted:• CONTROL:• Control endpoints are used to allow access to different parts of the USB device.• They are commonly used for configuring the device, retrieving information about the device, sending commands to the device, or retrieving status reports about the device. These endpoints are usually small in size.
  40. 40. • Every USB device has a control endpoint called “endpoint 0” that is used by the USB core to configure the device at insertion time.• These transfers are guaranteed by the USB protocol to always have enough reserved bandwidth to make it through to the device.• INTERRUPT:• Interrupt endpoints transfer small amounts of data at a fixed rate every time the USB host asks the device for data.• These endpoints are the primary transport method for USB keyboards and mice.• They are also commonly used to send data to USB devices to control the device, but are not generally used to transfer large amounts of data.• These transfers are guaranteed by the USB protocol to always have enough reserved bandwidth to make it through.
  41. 41. • BULK:• Bulk endpoints transfer large amounts of data. These endpoints are usually much larger (they can hold more characters at once) than interrupt endpoints.• They are common for devices that need to transfer any data that must get through with no data loss.• These transfers are not guaranteed by the USB protocol to always make it through in a specific amount of time.• 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. These endpoints are common on printers, storage, and network devices.• ISOCHRONOUS:• Isochronous endpoints also transfer large amounts of data, but the data is not always guaranteed to make it through.• These endpoints are used in devices that can handle loss of data, and rely more on keepinga constant stream of data flowing.• Real-time data collections, such as audio and video devices, almost always use these endpoints.
  42. 42. 2. Interfaces• USB endpoints are bundled up into interfaces. USB interfaces handle only one type of a USB logical connection, such as a mouse, a keyboard, or a audio stream.• Some USB devices have multiple interfaces, such as a USB speaker that might consist of two interfaces: a USB keyboard for the buttons and a USB audio stream.• Because a USB interface represents basic functionality, each USB driver controls an interface; so, for the speaker example, Linux needs two different drivers for one hardware device.
  43. 43. 3. Configurations• USB interfaces are themselves bundled up into configurations.• A USB device can have multiple configurations and might switch between them in order to change the state of the device.• For example, some devices that allow firmware to be downloaded to them contain multiple configurations to accomplish this.• A single configuration can be enabled only at one point in time.• Linux does not handle multiple configuration USB devices very well, but, thankfully, they are rare.
  44. 44. • USB devices are quite complex and are made up of lots of different logical units.• The relationships among these units can be simply described as follows:A. Devices usually have one or more configurations.B. Configurations often have one or more interfaces.C. Interfaces usually have one or more settings.D. Interfaces have zero or more endpoints.
  45. 45. References• Websites o o• Books o Linux Device Driver • By Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman
  46. 46. Thank You!!!